Spring AOP用于接口和其中的注释方法

时间:2014-10-02 10:27:22

标签: java spring aop

我有这样的服务代码:

@Component
public class MyService implements com.xyz.WithSession {

    public void someMethodWhichDoesNotNeedAutorization() {
        // code S1
    }

    @com.xyz.WithAuthorization
    public void someMethodWhichNeedAutorization() {
        // code S2
    }
}

和这样的方面:

@Aspect
public class MyAspect {

    @Before("target(com.xyz.WithSession)")
    public void adviceBeforeEveryMethodFromClassImplementingWithSession() {
        // code A1
    }

    @Before("target(com.xyz.WithSession) && @annotation(com.xyz.WithAuthorization)")
    public void adviceBeforeWithAuthorizationMethodFromClassImplementingWithSession() {
        // code A2
    }

注释看起来像:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WithAuthorization{
}
  • 在代码S1 - OK
  • 之前调用代码A1
  • 在代码S2之前调用代码A1 - 确定
  • 代码A2在代码S2之前未被调用 - 不行

我做错了什么?

使用Spring 3.1.3在Java 7中编写代码。

更新

我尝试过另一种方式。我使用'Around'建议而不是'Before'和'After'来访问ProceedingJoinPoint。在这个建议中,我用反射检查方法是否有注释'com.xyz.WithAuthorization':

private boolean isAnnotated(ProceedingJoinPoint proceedingJoinPoint) {
    MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
    return signature.getMethod().isAnnotationPresent(com.xyz.WithAuthorization);
}

我的注释有'@Retention(RetentionPolicy.RUNTIME)'但我在调试器中看到方法签名中运行时缺少注释。所以问题依然存在。

3 个答案:

答案 0 :(得分:3)

this link

的Spring Reference中

<强> e.g。在Spring参考

@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")
public void audit(Auditable auditable) {
    AuditCode code = auditable.value();
    // ...
}

执行AccountService接口定义的任何方法:

execution(* com.xyz.service.AccountService.*(..))

任何连接点(仅在Spring AOP中执行方法),其中执行方法具有@Transactional注释:

@annotation(org.springframework.transaction.annotation.Transactional)

我建议你使用......

@Before("execution(* com.xyz.WithSession.*(..)) && @annotation(authorization)")
public void adviceBeforeWithAuthorizationMethodFromClassImplementingWithSession(WithAuthorization authorization) {
    // code A2
}

答案 1 :(得分:2)

你的第二次切入点

@Before("target(com.xyz.WithSession) && @annotation(com.xyz.WithAuthorization)")

以两种方式失败。首先

target(com.xyz.WithSession)

仅匹配类,而不匹配方法。所以像@Xstian指出你应该使用

的内容
execution(* com.whatever.MyService.*(..))

匹配MyService类中的所有方法。

第二个问题是

@annotation(com.xyz.WithAuthorization)

其中参数应该是与通知中的参数名称匹配的名称。因此,您使用@annotation(someArgumentName),然后将com.xyz.WithAuthorization someArgumentName作为您的建议方法参数。

答案 2 :(得分:1)

可能您的注释没有运行时保留期:

@Retention(RetentionPolicy.RUNTIME)
public @interface WithAuthorization {}