所以我有一个生成的类(PartnerConnection),它为Salesforce云平台提供DML操作。我们遇到的问题是,由于与Salesforce或运行代码的系统的连接问题,我们长期运行的集成过程失败。
为了解决这个问题,我用我命名的PartnerConnection扩展了AdvancedPartnerConnection类。AdvancedPartnerConnection只是重写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中做。

最佳答案

您基本上想要捕获对所有对象方法的所有调用,并对所有对象方法应用一些逻辑。
您可以创建Proxy并在handler调用方法中重试。
使用这种基于方法签名的方法,您可以决定要做什么。
另一种方法可以使用AspectJ或任何其他AOP框架,但是您的用例添加这种依赖关系非常简单,imo。
如果您要添加的类不是您的类,那么这个解决方案可能不是最优雅的。但是如果您愿意牺牲一些优雅来获得可维护性(因为您没有复制代码),那么您可以:

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

要创建behaviour,必须使用类的所有方法创建proxy。这是一个糟糕的部分,但这不会给应用程序添加任何依赖项。
interface YourInterface {
    public void voidMethod();
    public int intMethod(int n);
}

接下来需要的是包含interfaceInvocationHandler
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);
        }
    }
}

请记住,这是从我的头顶开始的。但应该是这样的。
如果创建该接口对您来说是不可接受的,那么您可以查看一些behavior框架。

09-18 13:38