MethodInterceptor 的幾種用法(二)

前言

發現寫着寫着好像越來越偏離正軌了,果然還是知道得太少了;這篇算是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

最後

我的博客
我的GitHub

參考

  1. Spring @Async 的使用與實現
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章