美文网首页
基于自定义注解的方式使用Spring AOP

基于自定义注解的方式使用Spring AOP

作者: a乐乐_1234 | 来源:发表于2018-04-11 23:43 被阅读0次

    以前在xml中配置spring aop,切点用一个表达式定义,在大多数场景中,我们不想包名或方法名遵循统一的规则,要实现灵活的定义切点,比如自定义一个注解,标注在那个方法上,就切那个方法。下面的内容刚好符合上面的场景,当然只是基本的代码模板,你可以根据你的业务需求进行更复杂的封装,这里只是提取出通用的代码。

    定义PointcutAdvisor实现

    这里一般都是继承AbstractPointcutAdvisor类,需要子类提供Pointcut和Advice实例

    public class MyAnnotaionAdvisor extends AbstractPointcutAdvisor{
        private Advice advice;
        private Pointcut pointcut;
        
        //传入你自定义注解和MethodInterceptor实现
        public MyAnnotaionAdvisor (Class<? extends Annotation> annotationType,MethodInterceptor interceptor){
          this.advice = interceptor;
          this.pointcut = buildPointcut(annotationType);
        }
    
        @Override
        public Pointcut getPointcut() {
            Assert.notNull(this.pointcut, "'pointcut' must not be null");
            return this.pointcut;
        }
    
        @Override
        public Advice getAdvice() {
            Assert.notNull(this.advice, "'advice' must not be null");
            return this.advice;
        }    
    
        private Pointcut buildPointcut(Class<? extends Annotation> annotationType) {
            Assert.notNull(annotationType, "'annotationTypes' must not be null");
            ComposablePointcut result = null;
            //类级别
            Pointcut cpc = new AnnotationMatchingPointcut(annotationType, true);
            //方法级别
            Pointcut mpc = AnnotationMatchingPointcut.forMethodAnnotation(annotationType);
             //对于类和方法上都可以添加注解的情况
             //类上的注解,最终会将注解绑定到每个方法上
              if (result == null) {
                   result = new ComposablePointcut(cpc);
              }
            return result.union(mpc);
        }
    }
    

    定义Advice 实现

    Advice接口有多种方式,如BeforeAdvice,AfterAdvice,Interceptor,一般实现MethodInterceptor接口

    //你也可以继承或实现你的业务类
    public class MyInterceptor implements MethodInterceptor {
        
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            //获取目标类
            Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
            //获取指定方法
            Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
            //获取真正执行的方法,可能存在桥接方法
            final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
    
            //获取方法上注解
            Async async = AnnotatedElementUtils.findMergedAnnotation(userDeclaredMethod, Async.class);
            if (async == null) {
                async = AnnotatedElementUtils.findMergedAnnotation(userDeclaredMethod.getDeclaringClass(), Async.class);
            }
    
            //获取返回类型
            Class<?> returnType = invocation.getMethod().getReturnType();
            //返回类型判断
            if (User.class.isAssignableFrom(returnType)) {
    
                return null;
            }
    
            //执行具体业务逻辑
            
            return invocation.proceed();
        }
    
    }
    

    配置Advisor

      //在配置类或文件中创建该Bean
      public class MyAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor implements BeanFactoryAware {
         private MethodInterceptor  interceptor;
         private  Class<? extends Annotation> annotation;
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            setBeforeExistingAdvisors(true);
            StatAnnotationAdvisor advisor = new StatAnnotationAdvisor(this.annotation,this.interceptor);
            advisor.setBeanFactory(beanFactory);
            this.advisor = advisor;
        }
        //省略getter/setter方法
    }
    

    以上只是针对单个注解的AOP实现,那对于多个注解,每个注解都有不同的处理逻辑,怎么实现?这里使用的是Spring aop,如果希望在CGLIB中灵活配置,怎么实现?不着急,后面慢慢写。

    相关文章

      网友评论

          本文标题:基于自定义注解的方式使用Spring AOP

          本文链接:https://www.haomeiwen.com/subject/usdtkftx.html