前言
最近在看springboot
的@EnableAsync
的源碼,發現還是需要提前看一些東西,比如這次的MethodInterceptor
接口的作用;如今springboot
都到2.0以后了,我谷歌出來好多文章都是用的配置文件,本篇就用純代碼的形式來說明MethodInterceptor
的用法;
正文
項目使用springboot
的2.3.0.RELEASE版本構建,其中需要注意導入aop
的starter
;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
注意: 在springboot
項目中若未加入上面的包,案例一會報錯,案例二不會報錯,但是不會生效;
非注解
以下兩個案例都是針對非注解的
案例一
使用aspectj execution
表達定義切點;這個就比較靈活了,主要就是看traceExecution
怎么去寫了;
- 自己寫一個類實現
MethodInterceptor
接口的invoke()
方法
public class MyInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println(methodInvocation.getMethod().getName());
return methodInvocation.proceed();
}
}
- 使用
AspectJExpressionPointcut
定義切點並注冊
@Configuration
public class InterceptorConfig {
//注意該地址為項目具體包地址
public static final String traceExecution = "execution(* com.example.methodinterceptor..*.*(..))";
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor2() {
MyInterceptor interceptor = new MyInterceptor();
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(traceExecution);
// 配置增強類advisor
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
advisor.setAdvice(interceptor);
return advisor;
}
}
案例二
這個案例主要是用JdkRegexpMethodPointcut
來構造切點,這個就看Pattern
參數怎么寫了;
- 自己寫一個類實現
MethodInterceptor
接口的invoke()
方法
public class MyInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println(methodInvocation.getMethod().getName());
return methodInvocation.proceed();
}
}
- 使用
JdkRegexpMethodPointcut
定義切點
@Configuration
public class InterceptorConfig {
@Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor() {
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPattern("com.example.methodinterceptor.*");
// 配置增強類advisor
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
advisor.setAdvice(new MyInterceptor());
System.out.println(advisor.toString());
return advisor;
}
}
注解
- 自定義注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InterceptorAnnotation {
}
案例三
這個案例就是案例一,只是將AspectJExpressionPointcut
的參數改變了Expression
;
直接使用案例一代碼,然后將traceExecution
修改就可以了
public static final String traceExecution = "annotation(com.example.methodinterceptor.annotation.InterceptorAnnotation)";
案例四
這個案例就是使用AnnotationMatchingPointcut
來構造切點;
- 自己寫一個類實現
MethodInterceptor
接口的invoke()
方法
public class MyInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println(methodInvocation.getMethod().getName());
return methodInvocation.proceed();
}
}
- 使用AnnotationMatchingPointcut構造切點
注意: 這是使用的AnnotationMatchingPointcut
構造方法;在參考文章1中使用的是:
AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(InterceptorAnnotation.class, true);
這個寫法並沒有對該注解進行攔截;在文章末尾的評論有提到這個問題;
@Configuration
public class InterceptorConfig {
@Bean
public Advisor pointcutAdvisor() {
MyInterceptor interceptor = new MyInterceptor();
AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(null,InterceptorAnnotation.class);
// 配置增強類advisor
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
advisor.setAdvice(interceptor);
System.out.println(advisor.toString());
return advisor;
}
}
總結
以上幾種案例感覺能滿足很多場景了,但是感覺每種場景都有很多案例支持,具體卻不知道選取哪一種,只有多看看源碼,去了解思想了;