前言
發現寫着寫着好像越來越偏離正軌了,果然還是知道得太少了;這篇算是MethodInterceptor
的第二篇了吧,本來沒想寫這篇文章的,但是看了看源碼,顛覆我之前已有的認知,感覺還是得把這篇文章寫出來;
正文
上一篇MethodInterceptor
的文章都是以配置註解的形式來將MethodInterceptor
註冊生效,這次這篇將使用spring
原生的類或接口來將MethodInterceptor
註冊並生效。
TestInterceptorAnnotation
先自定義註解TestInterceptorAnnotation
註解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestInterceptorAnnotation {
}
TestInterceptor
寫一個MethodInterceptor
的實現類TestInterceptor
:
public class TestInterceptor implements MethodInterceptor, Ordered {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("開始執行");
Object result = methodInvocation.proceed();
System.out.println("結束執行");
return result;
}
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
AnnotationAdvisor
寫一個AnnotationAdvisor
類,去繼承AbstractPointcutAdvisor
類,代碼如下:
public class AnnotationAdvisor extends AbstractPointcutAdvisor {
private Advice advice;
private Pointcut pointcut;
public AnnotationAdvisor() {
this.advice = new TestInterceptor();
}
@Override
public boolean isPerInstance() {
return false;
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
@Override
public Advice getAdvice() {
return this.advice;
}
public void setMyPointcut() {
this.pointcut = new AnnotationMatchingPointcut(null,TestInterceptorAnnotation.class);
}
public void setMyPointcutA() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* com.example.threaddemo..*.*(..))");
this.pointcut = pointcut;
}
public void setMyPointcutB() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("@annotation(com.example.threaddemo.annotation.TestInterceptorAnnotation)");
this.pointcut = pointcut;
}
public void setMyPointcutC() {
JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
pointcut.setPattern("com.example.threaddemo.*");
this.pointcut = pointcut;
}
// 以下的兩個方法是參考的EnableAsync源碼中的一部分代碼
public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
Set<Class<? extends Annotation>> asyncAnnotationTypes = new HashSet<Class<? extends Annotation>>();
asyncAnnotationTypes.add(asyncAnnotationType);
this.pointcut = buildPointcut(asyncAnnotationTypes);
}
protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
ComposablePointcut result = null;
for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(asyncAnnotationType);
if (result == null) {
result = new ComposablePointcut(cpc).union(mpc);
} else {
result.union(cpc).union(mpc);
}
}
return result;
}
}
這個代碼比較多,基本上把上一篇的代碼都帶過來了,這裏主要是注意構造切點的幾個方法;
AnnotationBeanPostProcessor
最關鍵的來了,新建類AnnotationBeanPostProcessor
,繼承AbstractBeanFactoryAwareAdvisingPostProcessor
:
//這裏注意將該類註冊進spring容器
@Component
public class AnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
AnnotationAdvisor advisor = new AnnotationAdvisor();
//這裏就看自己選擇哪一種切面方式了
advisor.setAsyncAnnotationType(TestInterceptorAnnotation.class);
this.advisor = advisor;
}
}
總結
這篇文章主要參考的EnableAsync
源碼的AsyncAnnotationBeanPostProcessor
類