MethodInterceptor 的几种用法
前言
最近在看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;
}
}
总结
以上几种案例感觉能满足很多场景了,但是感觉每种场景都有很多案例支持,具体却不知道选取哪一种,只有多看看源码,去了解思想了;