Spring AOP:Aspect没有处理被调用的方法

时间:2013-07-31 19:21:57

标签: java spring aop

这是我第一次使用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;
    }
}

Spring配置

<aop:aspectj-autoproxy />
<bean id="myAspect" class="com.pkg.MyAspect" />
<bean id="invalidSessionIdHandler" class="com.pkg.InvalidSessionIdHandler" />  
  1. 我的意图是当我致电myAspect.method1()时,如果method2抛出method2异常,那么只有InvalidSessionId才会调用method2重试。但上面的代码似乎没有做任何事情。它只是在从method2抛出异常后立即返回。但是,如果我将@RetryOnInvalidSessionId放在method1上,则会重试整个method1

  2. 为了学习我保持method2是公开的,但实际上我希望它是private。我在这里没有线索,如何重试私人方法。

  3. 任何建议都会有所帮助。

    由于

1 个答案:

答案 0 :(得分: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()this称为this.method2()this是对实际对象的引用,而不是代理。因此,它不会执行任何其他行为。

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

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