我现在已经浏览了网络和堆栈溢出数小时,而我似乎无法找到问题的解决方案。我的猜测是,对于那些比我更熟练的AOP来说,它是微不足道的,但是显而易见。
我们正在为我们的应用程序使用Spring Boot 1.2.6.RELEASE,我希望包含一个名为@Prohibited的自定义注释,以便能够根据用户的权限执行@Around建议设置和注释的值。
到目前为止,我只有一个空白注释,我希望我的建议可以围绕任何使用@Prohibited注释的方法执行。
注释:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface Prohibited {
}
方面:
@Aspect
@Component
public class PermissionAspect {
@Pointcut("execution(@com.whatever.commons.logic.permission.Prohibited * *(..))")
public void prohibited() {}
@Around("prohibited()")
public Object permit(final ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("########### - " + joinPoint.getSignature().getName());
joinPoint.proceed();
return null;
}
}
带注释的方法:
@Component
public class AnyService {
@Prohibited
public List<Object> anyMethod() {
//anything - assume a breakpoint here
}
}
在我的pom.xml中,我包含了spring-boot-starter-aop依赖项:
<!-- spring boot with aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
最后在application.properties文件中,我添加了以下行,以便使Spring能够围绕类创建代理,而不仅仅是接口:
spring.aop.proxy-target-class=true
现在我设置了一个断点到注释方法的第一行,并期望至少看到我在控制台中的建议打印出来,但它永远不会发生。
相反,应用程序在断点处挂起而不打印任何行。有趣的是,我可以在调用堆栈中看到确实为类创建了代理,我可以看到如下内容:
CglibAopProxy$CglibMethodInvocation.invokeJoinpoint() line: 717
CglibAopProxy$CglibMethodInvocation(ReflectiveMethodInvocation).proceed() line: 157
如果我注释掉@Prohibited注释,根本就没有生成代理,所以看起来Spring确实在我指定的类周围创建了一个CGLIB代理(显然是由于我方面定义的@Pointcut),但它确实不执行我的@Around建议,而只是进入连接点。
有谁知道我在这里缺少什么?我是否应该使用编译时编织(如果可能的话,我想避免这种情况)?
*更新*
我忘了提到的是如何实际调用该方法。从另一个服务(在这种情况下也称为控制器):
@RestController
public class AnyController {
@Autowired
AnyService anyService;
@RequestMapping("/this/that")
public ResponseEntity<Object> something() {
this.anyService.anyMethod();
}
}
问题是我注释了错误的方法(见下面的答案)。
答案 0 :(得分:1)
我明白了。我知道这很小,可能很傻。
在修改编译时编织后,我注意到我注释了错误的方法。我的服务有两个公共方法,而一个是调用另一个(毕竟可能不是一个好的设计),如下所示:
@Component
public class AnyService {
public Object firstMethod() {
//doing stuff...
this.secondMethod();
}
@Prohibited
public Object secondMethod() {
//here be breakpoint
}
}
因此,当断点命中时,我已经超出了代理,并且由于没有注释第一个方法,因此没有执行方面。
自我注意:方法调用必须来自服务外部,否则将无法通知代理。
我希望这会帮助某人遇到同样的问题。