3

这是我第一次使用 AOP,所以这可能是一个非常菜鸟的问题。

public class MyAspect implements AspectI {

public void method1() throws AsyncApiException {
    System.out.println("In Method1. calling method 2");
    method2();
}

@RetryOnInvalidSessionId
public void method2() throws AsyncApiException {
    System.out.println("In Method2, throwing exception");
    throw new AsyncApiException("method2", AsyncExceptionCode.InvalidSessionId);
}

public void login() {
    System.out.println("Logging");
}

InvalidSessionHandler 看起来像这样。

@Aspect
public class InvalidSessionIdHandler implements Ordered {

    @Around("@annotation(com.pkg.RetryOnInvalidSessionId)")
    public void reLoginAll(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Hijacked call: " + joinPoint.getSignature().getName() + " Proceeding");
        try {
            joinPoint.proceed();
        } catch (Throwable e) {
            if (e instanceof AsyncApiException) {
                AsyncApiException ae = (AsyncApiException) e;
                if (ae.getExceptionCode() == AsyncExceptionCode.InvalidSessionId) {
                    System.out.println("invalid session id. relogin");
                    AspectI myAspect = (AspectI) joinPoint.getTarget();
                    myAspect.login();
                    System.out.println("Login done. Proceeding again now");
                    joinPoint.proceed();
                }
            }
        }
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

弹簧配置

<aop:aspectj-autoproxy />
<bean id="myAspect" class="com.pkg.MyAspect" />
<bean id="invalidSessionIdHandler" class="com.pkg.InvalidSessionIdHandler" />  
  1. 我的意图是当我调用myAspect.method1()which 轮流调用method2时,如果method2抛出InvalidSessionId异常,则只method2应重试。但是上面的代码似乎没有做任何事情。它只是在从方法 2 引发异常后立即返回。@RetryOnInvalidSessionId但是,如果我穿上method1然后整个method1重试。

  2. 对于我保持的学习method2是公开的,但实际上我希望它是公开的private。我在这里不知道如何重试私有方法。

任何的意见都将会有帮助。

谢谢

4

1 回答 1

5

这在您当前的设置中是不可能的。使用 Spring 的 AOP 功能,您的类InvalidSessionIdHandler将被创建为 bean,然后扫描注释/方法签名/等。与您的MyAspect班级相关。它会找到method2()并因此创建一个代理来包装它已经创建的 bean。代理将具有您建议的行为。

Spring 会在你需要的地方注入这个(代理)bean。例如:

public class MyClass {
   @Autowired
   private MyAspect aspect;

   public void callMethod2() {
       aspect.method2();
   }
}

在这种情况下,MyClass对象具有对代理的引用。当它调用 时aspect.method2(),将执行添加的行为。

但是,在您的代码中,您希望method2()method1()

public void method1() throws AsyncApiException {
    System.out.println("In Method1. calling method 2");
    method2();
}

这是你的MyAspect班级。从技术上讲,这里发生的事情被method2()称为. 是对实际对象的引用,而不是代理。因此它不会执行任何额外的行为。thisthis.method2()this

AOP Spring 文档更详细地解释了这一点。

这里的解决方法是重构,以便method2()在另一个类/对象中或从外部调用它,即。不是从method1()

于 2013-07-31T19:46:38.880 回答