如何使这个代码DRYer

时间:2013-11-01 23:44:25

标签: java exception-handling dry

所以我有一个生成的类(PartnerConnection),它为SalesForce云平台提供DML操作。由于与SalesForce或运行代码的系统的连接问题,我们遇到了长时间运行的集成过程失败的问题。

为了解决这个问题,我将PartnerConnection类扩展为我所说的AdvancedPartnerConnectionAdvancedPartnerConnection只是覆盖 PartnerConnection的方法,并用 try / catch / retry 逻辑包装它们。

@Override
public QueryResult query(String queryString) throws ConnectionException{
    int attempt = 0;
    ConnectionException lastException = null;
    while(true){
        if(attempt < maxAttempts){ //maxAttempts constant
            if(lastException != null){
                try {
                    //exponentially increase wait times
                    Long sleepTime =(long) Math.pow(sleepBase, attempt) * 300;
                    Thread.sleep(sleepTime);
                } catch (InterruptedException e1) {
                    // something bad has happen, throw the connection exception
                    throw lastException;
                }
            }
            attempt ++;
            try{
                //call super class method
                return super.query(queryString);
            }catch(ConnectionException e){
                lastException = e;
            }
        }else{
            throw lastException;
        }
    }
}

我已经为少数超类方法实现了这个,唯一的区别是被调用的方法及其'参数。如果我决定更改任何重试逻辑,因为我希望它在所有方法中保持一致,这已经成为一种真正的痛苦。

有没有人有办法将重试逻辑提取到一个单独的类或方法中,并可能传入函数调用?我在.NET中做过这样的事情,但我不确定如何在java中做到这一点。

1 个答案:

答案 0 :(得分:1)

您基本上希望捕获对所有对象方法的所有调用,并对所有对象方法应用一些逻辑。  您可以创建Proxy并在handler调用方法中重试。

使用基于方法签名的方法,您决定要做什么。

另一种方法可以使用AspectJ或任何其他AOP框架,但您的用例非常简单,可以添加这种依赖关系,IMO。

如果要添加某些behaviour的类不是您的,那么此解决方案可能不是最优雅的。但是如果你愿意牺牲一些优雅来获得可维护性(因为你没有复制代码)那么你可以:

class NotYourClass {
    public void voidMethod() {}
    public int intMethod(int n) { return 0; }
}

要创建proxy,您必须使用该类的所有方法创建interface。这是一个糟糕的部分,但这不会为您的应用程序添加任何依赖。

interface YourInterface {
    public void voidMethod();
    public int intMethod(int n);
}

您需要的下一件事是InvocationHandler,其中包含behavior

class YourInvocationHandler implements InvocationHandler {
    private final NotYourClass target;

    public YourInvocationHandler(NotYourClass target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
                // Here you must look to the methods that are the ones that you want.
                return method..invoke(target, args);
        } catch (Exception e) {
            // Retry?
            method.invoke(target, args);
        }
    }
}

请记住,这是我的头脑。但应该是这样的。

如果创建该界面是您无法接受的,那么您可以查看一些AOP框架。