探究使用原生AspectJ时,@Aspect注解不生效和@Around环绕注解执行两次原因
1、@Around环绕注解执行两次原因
自定义一个注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface OperationLog { /** * 要操作的资源 * * @return 资源 */ String resource() default ""; }
为该注解定义切面
@Aspect public class OperationLogAspect { @Pointcut("@annotation(org.wenjie.operationlog.OperationLog)") private void operationLog() {} @Around("operationLog()") public Object operator(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("hello-world"); joinPoint.proceed(); return null; } }
方法测试
class OperationLogAspectTest { @Test void name() { say("Smith", 108); } @OperationLog() public void say(String name, int age) { System.out.println(name + " current age is " + age); } }
测试结果:
debug
其实,这属于Ajc编译器的一个Bug,详见Ajc-bug
所以,到这一步,问题就很清晰了,因为Ajc编辑器的bug,导致了在main方法中也织入了通知,所以在执行的时候,输出了两次日志。
解决方法
方案一
因为两次调用的kind属性不一样,所以可以通过kind属性来判断时候调用切面。这样显得不优雅,而且如果切面有更多的逻辑的话,需要加各种if-else的判断,所以不推荐。
方法二
更优雅的方案是修改@Around("@annotation(StatsService)")的逻辑,改为@Around("execution(* *(..)) && @annotation(StatsService)")。
重新运行上面的测试类,结果如下:
2、@Aspect注解不生效问题
在pom文件中添加一个插件配置
<build> <plugins> <!--使用原生的AspectJ必须添加如下插件,否则{@code @AspectJ}注解不会生效--> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> <complianceLevel>1.8</complianceLevel> </configuration> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了