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>