springAOP源码1

作者: 念䋛 | 来源:发表于2021-09-20 08:27 被阅读0次

    在介绍AOP之前先讲解一下advice和advisor,以及调用链
    先从advice介绍
    被代理的类

    @Component
    public class CalculateTest {
        public int add(int i, int j) {
            System.out.println ("加");
            return i + j;
        }
    
        public int subtract(int i, int j) {
            System.out.println ("减");
            return i - j;
        }
    
        public int multiply(int i, int j) {
            System.out.println ("乘");
            return i * j;
        }
    
        public int divide(int i, int j) {
            System.out.println ("除");
            return i / j;
        }
    }
    

    下面为两个advice 前后过滤器

    public class LogAdviceAfter implements AfterReturningAdvice {
    
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
            String methodName = method.getName();
            System.out.println("执行目标方法【"+methodName+"】的<后置通知>,入参"+ Arrays.asList(args)+"得到的结果"+returnValue);
        }
    }
    
    public class LogAdviceBefore implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            String methodName = method.getName();
            System.out.println("执行目标方法【"+methodName+"】的<前置通知>,入参"+ Arrays.asList(args));
        }
    }
    
    

    Interceptor拦截器

    public class LogIntreceptor implements MethodInterceptor {
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            System.out.println ("MethodInterceptor方法调用前");
            Object proceed = invocation.proceed ();
            System.out.println ("MethodInterceptor方法调用后");
            return proceed;
        }
    }
    
    

    配置类

    @Configuration
    @ComponentScan(basePackages = "springlearn.aspectjtest")
    public class ConfigurationAspectJ {
      
        //以类为单位,不能精确到方法,而且多个类需要多个代理
        //在ioc,如果要使用代理那么bean的名称为proxyFactoryBean,bean名称为calculateTest是未代理的类
        //这里要注意的是CalculateTest不能是cglib代理之后的类,@Configuration是不可以的,可以使用@Component
     @Bean
    public ProxyFactoryBean proxyFactoryBean(CalculateTest calculateTest ) {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean ();
    //可以指定advice也可以执行interecptor
        proxyFactoryBean.setInterceptorNames ("adviceBefore","logIntreceptor");
        proxyFactoryBean.setTarget (calculateTest);
        return proxyFactoryBean;
    }
    @Bean
        public LogAdviceBefore logAdviceBefore() {
            return new LogAdviceBefore ();
        }
        @Bean
        public LogAdviceAfter logAdviceAfter() {
            return new LogAdviceAfter ();
        }
    @Bean
    public LogIntreceptor logIntreceptor() {
        return new LogIntreceptor ();
    }
    
    }
    
    public class Main {
        public static void main(String[] args) {
            //查找配置类.配置类有扫描类的路径,满足条件的放到容器中
            AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext (ConfigurationAspectJ.class);
    //获取代理类,bean的名称为proxyFactoryBean,其实就是调用了FactoryBean的getObject方法
            CalculateTest calculateTestProxy = ( CalculateTest ) configApplicationContext.getBean ("proxyFactoryBean");
            int divide = calculateTestProxy.divide (4, 2);
            int add = calculateTestProxy.add (4, 2);
            configApplicationContext.close ();
        }
    }
    

    得到的结果


    image.png

    Advisor包含了advice和Pointcut,拦截方法和拦截方法做什么.
    配置类

    @Configuration
    @ComponentScan(basePackages = "springlearn.aspectjtest")
    public class ConfigurationAspectJ {
    
        //通知(advice):通知类,没有切点 举例:LogAdvice实现了MethodBeforeAdvice接口,切面为CalculateTest类的add和divide方法,LogAdvice会在执行add和divide方法前,执行LogAdvice的before方法,LogAdvice就是通知类
        //通知者(advisor):  包含了advice和切点,切点为方法名称,注意这里没有规定哪个类,类是在ProxyFactoryBean中定义的
        @Bean
        public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisorBefore() {
            NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor ();
            nameMatchMethodPointcutAdvisor.setAdvice (logAdviceBefore ());
            nameMatchMethodPointcutAdvisor.setMappedNames ("divide", "add");
            return nameMatchMethodPointcutAdvisor;
        }
    
        @Bean
        public NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisorAfter() {
            NameMatchMethodPointcutAdvisor nameMatchMethodPointcutAdvisor = new NameMatchMethodPointcutAdvisor ();
            nameMatchMethodPointcutAdvisor.setAdvice (logAdviceAfter ());
            nameMatchMethodPointcutAdvisor.setMappedNames ("divide", "add");
            return nameMatchMethodPointcutAdvisor;
        }
    
        @Bean
        public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
            BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator ();
    //以通配符的方式模糊匹配,这样就不用每个类写一个代理
            beanNameAutoProxyCreator.setBeanNames ("calculateTest*");
            //多个过滤器组成调用链
            beanNameAutoProxyCreator.setInterceptorNames ("nameMatchMethodPointcutAdvisorBefore", "nameMatchMethodPointcutAdvisorAfter");
            return beanNameAutoProxyCreator;
        }
    
    
        @Bean
        public LogAdviceBefore logAdviceBefore() {
            return new LogAdviceBefore ();
        }
    
        @Bean
        public LogAdviceAfter logAdviceAfter() {
            return new LogAdviceAfter ();
        }
    
        @Bean
        public LogIntreceptor logIntreceptor() {
            return new LogIntreceptor ();
        }
    }
    
    
    public class Main {
        public static void main(String[] args) {
            //查找配置类.配置类有扫描类的路径,满足条件的放到容器中
            AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext (ConfigurationAspectJ.class);
            //bean的名称为calculateTest,类的本身已经被代理了
            CalculateTest calculateTest = ( CalculateTest ) configApplicationContext.getBean ("calculateTest");
            int divide = calculateTest.divide (4, 2);
            int add = calculateTest.add (4, 2);
            configApplicationContext.close ();
        }
    }
    
    image.png

    Advisor可以指定代理的方法和拦截器,多个Advisor形成了调用链,
    BeanNameAutoProxyCreator通过名称的方式,将类和Advisor绑定在一起,名称可以使用*作为通配符,这样就可以匹配多个类.
    上面讲解了advice和advisor,这样有助于理解AOP的源码.

    下面分析AOP的源码,Spring在引入组件的是常用的一种是@EnableXXXX,下面就从
    @EnableAspectJAutoProxy入手分析源码
    @EnableAspectJAutoProxy的import注解
    @Import(AspectJAutoProxyRegistrar.class)
    AspectJAutoProxyRegistrar接口继承了ImportBeanDefinitionRegistrar
    在springioc容器源码的时候分析过,继承ImportBeanDefinitionRegistrar会调用
    registerBeanDefinitions方法
    那么在AspectJAutoProxyRegistrar的registerBeanDefinitions方法中会调用
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    代码最终将AnnotationAwareAspectJAutoProxyCreator.class注册进beanDefinitionMap中
    AnnotationAwareAspectJAutoProxyCreator类继承图
    [图片上传失败...(image-4f9378-1632042893525)]
    可以看到AnnotationAwareAspectJAutoProxyCreator继承了很多的Bean的后置处理器,
    我们分析过bean的后置处理器的9处调用,AOP的advisor包装和创建cglib动态代理都是在bean的后置处理器中完成的

    1. InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation方法的调用.
      真正执行AnnotationAwareAspectJAutoProxyCreator#postProcessBeforeInstantiation
      其主要的作用是创建Advisor,并缓存起来
    @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    //缓存,不用重复的查找,第一次为空  
    
    Object cacheKey = getCacheKey(beanClass, beanName);
    
     if (!StringUtils.*hasLength*(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; }
    
    // advisedBeans成员变量,如果为false是不需要代理的,比如Advice的子类或者标注了@Aspect的类,本身是服务于代理类的,当然是不需要代理的
    
    // isInfrastructureClass(beanClass)判断beanClass不是Advice,Pointcut,Advisor,AopInfrastructureBean类及子类,
    
    //重点shouldSkip方法,获取beanDefinitionMap中关于AOP的类(Advice的实现类和标注了@Aspect注解的类),我们这里只关注了是标注@Aspect注解的类, shouldSkip下面会分析 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.*FALSE*);
     return null; }
     } // Create proxy here if we have a custom TargetSource.
     // Suppresses unnecessary default instantiation of the target bean:
     // The TargetSource will handle target instances in a custom fashion. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
     if (targetSource != null) { if (StringUtils.*hasLength*(beanName)) { this.targetSourcedBeans.add(beanName); }
     Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
     this.proxyTypes.put(cacheKey, proxy.getClass());
     return proxy; } return null; }
    

    shouldSkip方法中的findCandidateAdvisors()方法,寻找Advice的实现类和标注了@Aspect的类, findCandidateAdvisors()被重写了,那我们关注重写的方法
    AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
    super. findCandidateAdvisors寻找beanDefinitionMap中所有Advisor的子类
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());查找标注了@AsceptJ注解的类,并把所有找到的类包装为Advisor类,那我们就分析
    this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法

    public List<Advisor> buildAspectJAdvisors() {
    //从缓存中获取标注了@Aspect的类
       List<String> aspectNames = this.aspectBeanNames;
    
       if (aspectNames == null) {
    //线程安全,防止多线程加载@Aspect
          synchronized (this) {
             aspectNames = this.aspectBeanNames;
    //单例模式中的双重校验,提高效率
             if (aspectNames == null) {
                List<Advisor> advisors = new ArrayList<>();
                aspectNames = new ArrayList<>();
    //从bean定义Map中获取Object的子集,也就是获取所有的bean定义
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                      this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                   if (!isEligibleBean(beanName)) {
                      continue;
                   }
                   // We must be careful not to instantiate beans eagerly as in this case they
                   // would be cached by the Spring container but would not have been weaved.
    //获取类
                   Class<?> beanType = this.beanFactory.getType(beanName, false);
                   if (beanType == null) {
                      continue;
                   }
    //判断类是否标注了@Aspect注解
                   if (this.advisorFactory.isAspect(beanType)) {
                      aspectNames.add(beanName);
                      AspectMetadata amd = new AspectMetadata(beanType, beanName);
                      if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                         MetadataAwareAspectInstanceFactory factory =
                               new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
    //将类中标注了Pointcut.class, Around.class, Before.class, After.class, //AfterReturning.class, AfterThrowing.class 注解的方法,经过组合,封装成
    //InstantiationModelAwarePointcutAdvisorImpl的实例集合
    //每个InstantiationModelAwarePointcutAdvisorImpl包含Advice和PointCut
    //方法不跟进去了,主要脉络是首先找到除标注@Pointcut注解的方法,再去掉Object自带
    //方法(equal,hashCode,notify等),包装为Advisor
                         List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                         if (this.beanFactory.isSingleton(beanName)) {
    //将Advisor缓存起来,key为bean的名称,这里是所有类的产出的Advisor缓存起来
                            this.advisorsCache.put(beanName, classAdvisors);
                         }
                         else {
                            this.aspectFactoryCache.put(beanName, factory);
                         }
                         advisors.addAll(classAdvisors);
                      }
                      else {
                         // Per target or per this.
                         if (this.beanFactory.isSingleton(beanName)) {
                            throw new IllegalArgumentException("Bean with name '" + beanName +
                                  "' is a singleton, but aspect instantiation model is not singleton");
                         }
                         MetadataAwareAspectInstanceFactory factory =
                               new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                         this.aspectFactoryCache.put(beanName, factory);
                         advisors.addAll(this.advisorFactory.getAdvisors(factory));
                      }
                   }
                }
                this.aspectBeanNames = aspectNames;
                return advisors;
             }
          }
       }
    //将得到的InstantiationModelAwarePointcutAdvisor存放到缓存中
       if (aspectNames.isEmpty()) {
          return Collections.emptyList();
       }
       List<Advisor> advisors = new ArrayList<>();
       for (String aspectName : aspectNames) {
          List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
          if (cachedAdvisors != null) {
             advisors.addAll(cachedAdvisors);
          }
          else {
             MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
             advisors.addAll(this.advisorFactory.getAdvisors(factory));
          }
       }
       return advisors;
    }
    

    shouldSkip方法在判断类是否需要跳过(跳过就是map中的value为false不需要代理的意思)的同时,找到@Aspect和Advice的子类,并存放到缓存中

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
       if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
          return bean;
       }
       if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
          return bean;
       }
       if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
          this.advisedBeans.put(cacheKey, Boolean.FALSE);
          return bean;
       }
    
       // Create proxy if we have advice.
       Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
       if (specificInterceptors != DO_NOT_PROXY) {
          this.advisedBeans.put(cacheKey, Boolean.TRUE);
          Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
          this.proxyTypes.put(cacheKey, proxy.getClass());
          return proxy;
       }
    
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return bean;
    }
    
    1. BeanPostProcessor# postProcessorsAfterInitialization后置处理器
      真正执行的是AbstractAutoProxyCreator#postProcessorsAfterInitialization
      其主要作用遍历bean定义,与Advisor匹配,如果匹配成功则创建动态代理
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
       if (bean != null) {
          Object cacheKey = getCacheKey(bean.getClass(), beanName);
          if (this.earlyProxyReferences.remove(cacheKey) != bean) {
             return wrapIfNecessary(bean, beanName, cacheKey);
          }
       }
       return bean;
    }
    

    warpIfNecessary是重要方法

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
       if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
          return bean;
       }
    //判断是否不需要代理
       if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
          return bean;
       }
    //重复的判断
       if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
          this.advisedBeans.put(cacheKey, Boolean.FALSE);
          return bean;
       }
    
       // Create proxy if we have advice.
    //如果类中只要有一个方法满足了Advisor,这该类需要代理,下面会分析到
       Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    //如果匹配成功则创建代理类
       if (specificInterceptors != DO_NOT_PROXY) {
          this.advisedBeans.put(cacheKey, Boolean.TRUE);
    //创建代理类
          Object proxy = createProxy(
                bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
          this.proxyTypes.put(cacheKey, proxy.getClass());
          return proxy;
       }
    
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return bean;
    }
    
    

    调用的是AbstractAdvisorAutoProxyCreator重写的方法
    AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
    继续调用List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    下面为findEligibleAdvisors方法

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
       //获取所有的Advisor
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //判断类是否满足AspectJ的切点表达式,主要分两步初步筛选和精确筛选
       List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    //添加了自带的Advisor
       extendAdvisors(eligibleAdvisors);
    //进行排序,如果beanClass满足了两个AspectJ标注的类,比如都有@Before,那用@Order
    //来判断前后,是一种包裹的关系 比如  before1前置  before2 前置 after2后置 
    //after1后置 1把2包裹起来
       if (!eligibleAdvisors.isEmpty()) {
          eligibleAdvisors = sortAdvisors(eligibleAdvisors);
       }
       return eligibleAdvisors;
    }
    
    

    当beanClass匹配至少一个Advisor就可以创建代理了
    Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new
    SingletonTargetSource(bean));
    createProxy创建代理类后续继续分析

    相关文章

      网友评论

        本文标题:springAOP源码1

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