可插拔错误处理策略 [英] Pluggable Error Handling Strategy

查看:111
本文介绍了可插拔错误处理策略的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有服务对象(Service A),它有一些特定的重复异步任务。该服务对象还具有监督对象(服务B)。我想处理服务A中特定任务的大部分错误,只有在需要采取任何其他措施(例如服务A不知道如何处理错误时)才能通知服务B.)



由于服务A依赖于外部资源(例如网络可用性),有许多不同的例外,可以抛出,我现在不知道所有这些。



因为我也想在服务A中有一个可插拔的错误处理策略,以便它可以不同地处理不同的异常。我想使用我的IoC容器插入这些stratgies。



示例A:
服务A应该每30秒下载一次。 (轮询),但网址格式错误,因此会抛出MalformedURLException。 A查找MalformedURLExcpetion的错误处理策略,在这种情况下,策略将意味着取消下载并通过回调通知服务B(主管)。



示例B:
服务A应该下载的东西,但主机名无法解决。再次抛出异常(现在不知道确切类型),并且将查找相应的策略:在这种情况下,应该停止下载并在另一时间重试,直到某个阈值被击中。



我现在的问题是:如何实现错误处理策略和策略本身的动态查询?有没有一个模式?

解决方案

嗯,最简单直接的解决方案是使用简单的java try catch,而不是这种灵活但通常有用的错误处理策略并不会经常发生变化。您无法捕获的这些异常在方法上声明可能会被抛出,并且可能由您的对象B处理。



如果您希望更灵活。为您的服务A创建一个接口,并声明所有可能的异常。使用逻辑实现该接口,但不进行任何错误处理。然后,您可以创建实现该接口的ErrorStrategy对象,并将传入的调用委托给该接口的另一个实现,但这是有趣的部分为一个或多个特定异常附加了一些错误处理策略。这是一个例子,使其更容易理解。

  public interface A {
void someMethod()抛出IOException,MalformedURLException ;
}

class AImpl实现一个{
@Override
public void someMethod()throws IOException,MalformedURLException {
//这里有你的业务逻辑
}
}

class ErrorHandlerOne实现A {

@Override
public void someMethod()throws IOException {
try {
delegate.someMethod();
} catch(MalformedURLException e){
//处理异常
}
}
}

如果你想要更灵活,我建议使用AOP机制,而不是简单的代理链,这样你可以轻松插入和交换你的错误处理策略。如果您使用Spring和您的服务A是一个Spring Bean,您可以轻松地使用AOP支持中的Springs构建。在这种情况下,抛出的建议是你寻找的。

抛出建议之后:如果方法通过抛出异常退出,则要执行的建议。

  import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.AfterThrowing;

@Aspect
public class AfterThrowingExample {

@AfterThrowing(
pointcut =com.xyz.myapp.A.someOperation()
throwing =ex)
public void doRecoveryActions(IOException ex){
// ...
}
}


I have service object (Service A), that has some specific repetitive asynchronous task . This service object also has a supervising object (Service B). I want to handle most of the errors concerning the specific task in Service A and only inform Service B if it needs to take any additional measures (e.g. when Service A does not know how to handle the error).

Since Service A depends on external resources (e.g. network availabilty) there are many different exceptions, that can be thrown and I do not know all of them right now.

Because of that I would also like to have a pluggable eror-handling strategy inside Service A so that it can handle different exceptions differently. I would like to plug in those stratgies using my IoC container.

Example A: Service A is supposed to download something every 30 sec. (polling), but the URL is malformed so a MalformedURLException is thrown. A looks up the error handling strategy for MalformedURLExcpetion and in this case the strategy will mean canceling the download and informing Service B (the supervisor) via a callback.

Example B: Service A is supposed to download something, but the hostname cannot be resolved. Again an Exception is thrown (sorry don't know exact type now) and the corresponding strategy will be looked up: in this case the download should be stalled and retried at another time until a certain threshold is hit.

My problem now: How should I implement this dynamic lookup of error handling strategies and the strategies themselves? Is there a pattern for that?

解决方案

Well, the easiest and straight forward solution would be tu use plain java try catchs, not that flexible, but often useful enough as error handling strategies does not change that often. Those exceptions you can not catch are declared on the method to may be thrown, and may be handled by your Object B.

If you wanna be more flexible. Create an interface for your service A with all the possible exceptions declared. Implement that interface with logic but without any error handling. Then you could create ErrorStrategy objects that implement the interface as well and delegate incoming calls to another implementation of that interface, BUT and this is the interesting part append some error handling strategy for one or more particular exceptions. Here is an example to make it more understandable.

public interface A {
    void someMethod() throws IOException, MalformedURLException;
}

class AImpl implements A {
    @Override
    public void someMethod() throws IOException, MalformedURLException {
        // here goes your business logic
    }
}

class ErrorHandlerOne implements A {

    @Override
    public void someMethod() throws IOException {
        try {
            delegate.someMethod();
        } catch (MalformedURLException e) {
            // handle the exception
        }
    }
}

If you wanna be even more flexible, I would recommend to use AOP mechanisms instead of the simple delegation chain, that way you can easily plug-in and exchange your error handling strategies. If you use Spring and your Service A is a Spring-Bean you could easily use Springs build in AOP support. In that case the after throwing advice is what you looking for.

After throwing advice: Advice to be executed if a method exits by throwing an exception.

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterThrowing;

@Aspect
public class AfterThrowingExample {

  @AfterThrowing(
     pointcut="com.xyz.myapp.A.someOperation()"
     throwing="ex")
  public void doRecoveryActions(IOException ex) {
    // ...
  }
}

这篇关于可插拔错误处理策略的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆