3

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

为了解决这个问题,我PartnerConnection用我命名的类扩展了一个AdvancedPartnerConnection. AdvancedPartnerConnection只是覆盖了的方法并用try/catch/retry逻辑PartnerConnection包装它们。

@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 中做到这一点。

4

1 回答 1

1

您基本上想要捕获对所有对象方法的所有调用并将一些逻辑应用于所有这些方法。您可以创建一个代理并在处理程序调用方法中重试。

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

可以使用另一种方法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框架。

于 2013-11-01T23:50:04.697 回答