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之前未调用--不正常
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)