Java SpringAOP用于接口和其中带注释的方法

Java SpringAOP用于接口和其中带注释的方法,java,spring,aop,Java,Spring,Aop,我有如下服务代码: @Component public class MyService implements com.xyz.WithSession { public void someMethodWhichDoesNotNeedAutorization() { // code S1 } @com.xyz.WithAuthorization public void someMethodWhichNeedAutorization() {

我有如下服务代码:

@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
    }
这方面:

@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{
}
  • 代码A1在代码S1之前被调用--OK
  • 代码A1在代码S2之前被调用——OK
  • 代码A2在代码S2之前未调用--不正常
我做错了什么?

代码是用Java7和Spring3.1.3编写的

更新 我试过另一种方法。我使用“周围”建议而不是“之前”和“之后”来访问ProceedingJoinPoint。在本建议中,我使用反射检查方法是否具有注释“com.xyz.WithAuthorization”:

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

我的注释具有“@Retention(RetentionPolicy.RUNTIME)”,但我在调试器中看到,在方法签名的运行时缺少注释。因此问题仍然存在。

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

@Retention(RetentionPolicy.RUNTIME)
具有授权{}的公共@接口
位于弹簧参考中

例如,在弹簧参考中

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

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

我建议你用

@Before("execution(* com.xyz.WithSession.*(..)) && @annotation(authorization)")
public void adviceBeforeWithAuthorizationMethodFromClassImplementingWithSession(WithAuthorization authorization) {
    // code A2
}
你的第二个切入点

@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
作为您的建议方法参数。

您可以添加注释的代码吗?好的,添加到问题描述中。正如我前面所说的,如果您希望获得合格的帮助,请提供一个示例,以使问题可以重现。在我看来,注释不在那里似乎是不可能的。编译器不会删除它,除非它有错误。我认为问题出在别处,但猜测对你没有帮助。所以请…猜猜对我帮助很大。我仍然不能100%确定问题出在哪里,我不能提供SSCCE,因为它是一个太复杂的系统,我无法单独尝试重新创建这个案例。我意识到的重要一点是,MyService由HttpInvokerServiceExporter代理,这可能是注释未被捕获的原因。所以我解决了这个问题,通过使用MyService中的所有方法实现MyServiceWithSession接口,在其上添加注释,并在aspect中通过反射检查注释是否存在。可以进行注释,但只能对注释类进行注释,而不能对方法和接口进行注释。因此,如果您在Spring中使用默认的Java动态代理(即针对接口),它将无法工作。CGLIB与类一起工作,这可能会起作用。在您的示例中,您注释了一个方法。正如链接到
@Inherited
的Javadoc中所解释的那样,这两种方式都不起作用。遗憾的是,它有运行时保留。我试图用纯AspectJ重现这种情况,因为我不是Spring用户。它在那里工作,所以它在春天也应该工作。也许您有配置问题。请在GitHub上提供一个可复制的方法,以使问题可复制。我不能使用“execution(*com.xyz.WithSession.*(..),因为服务中的方法不是来自此空的WithSession接口。我不能使用“execution(*com.xyz.WithSession.*(..)”因为服务中的方法不是来自这个空的WithSession接口。@vertti我们的两个解决方案或多或少是相等的:D。。太好了!,这意味着这是一种正确的方式:D@nkoder将答案改为目标
MyService
@annotation(com.xyz.WithAuthorization)