• 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 的使用与实现
  • 相关阅读:
    大牛总结的Linux提权Exp合集
    CTF中图片隐藏文件分离方法总结
    解压报错gzip: stdin: not in gzip format tar: Child returned status 1 tar: Error is not recoverable: exiting now的解决方法
    CTF中常见Web源码泄露总结
    解决“当前扩展缓存策略没有进行注册”的错误
    【红色警报】XXE 高危漏洞将大面积影响微信支付安全,可能导致系统沦陷,请升级你的系统!
    Senparc.Weixin SDK v5.0 升级公告
    使用 VSTS 进行 CI 的过程中,无法识别 .NET Core 2.x 的情况处理
    .net core DI 注册 Lazy<> 类型
    【备忘】ASP.NET MVC 5 升级到 ASP.NET Core MVC 的部分变化
  • 原文地址:https://www.cnblogs.com/guoyuchuan/p/13227604.html
Copyright © 2020-2023  润新知