spring中aop的源码解析(三)

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

spring中aop的源码解析(三)

我们继续查看AbstractAspectJAutoProxyCreator中的wrapIfNecessary方法

    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

这里是获取通知

    protected Object[] getAdvicesAndAdvisorsForBean(
          Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
      //获取可用的Advisor列表
       List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
       if (advisors.isEmpty()) {
          return DO_NOT_PROXY;
       }
       return advisors.toArray();
    }

上面方法很简单讲任务委派到findEligibleAdvisors方法上面去。

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
       //获取所有候选Advisor列表
       List<Advisor> candidateAdvisors = findCandidateAdvisors();
      //从候选Advisor列表中找出那些能够适用于该类
       List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
       extendAdvisors(eligibleAdvisors);
       if (!eligibleAdvisors.isEmpty()) {
         //对Advisor进行排序这里排序设计到Order
          eligibleAdvisors = sortAdvisors(eligibleAdvisors);
       }
       return eligibleAdvisors;
    }

下面我们先从获取所有候选Advisor

    protected List<Advisor> findCandidateAdvisors() {
       //网上说这里是从xml配置文件中获取候选的advisor列表
       List<Advisor> advisors = super.findCandidateAdvisors();
       //这里是从所有扫描加载进来的类中获取候选advisor列表
       if (this.aspectJAdvisorsBuilder != null) {
          advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
       }
       return advisors;
    }

由于现在项目基本不用xml了加载bean我们就不进入分析直接看下面

BeanFactoryAspectJAdvisorsBuilder下面方法

    public List<Advisor> buildAspectJAdvisors() {
       List<String> aspectNames = this.aspectBeanNames;

       if (aspectNames == null) {
          synchronized (this) {
             aspectNames = this.aspectBeanNames;
             if (aspectNames == null) {
                List<Advisor> advisors = new LinkedList<>();
                aspectNames = new LinkedList<>();
                //这里获取所有加载到spring容器中的对象名称
                String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                      this.beanFactory, Object.class, true, false);
                for (String beanName : beanNames) {
                   //判断是否为有效的bean
                   if (!isEligibleBean(beanName)) {
                      continue;
                   }
                   //根据名称获取类对象
                   Class<?> beanType = this.beanFactory.getType(beanName);
                   if (beanType == null) {
                      continue;
                   }
                   //如果类对象上面存在@Aspect注解
                   if (this.advisorFactory.isAspect(beanType)) {
                      aspectNames.add(beanName);
                      //创建Aspect元数据
                      AspectMetadata amd = new AspectMetadata(beanType, beanName);
                      //如果类时单例
                      if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                        //创建元数据aop实例化工厂
                         MetadataAwareAspectInstanceFactory factory =
                               new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                          //从工厂里面获取通知列表
                         List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                         if (this.beanFactory.isSingleton(beanName)) {
                            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;
             }
          }
       }

       if (aspectNames.isEmpty()) {
          return Collections.emptyList();
       }
       List<Advisor> advisors = new LinkedList<>();
       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;
    }

我们重点分析ReflectiveAspectJAdvisorFactory 上面的getAdvisors

    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
      //获取工厂上面保存的aop类对象
       Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
       //获取工厂类上面保存aop类的名称
       String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
       validate(aspectClass);

       MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
             new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

       List<Advisor> advisors = new LinkedList<>();
       //这里是整个方法的核心 获取aop类上面所有的方法一次遍历获取上面的通知
       for (Method method : getAdvisorMethods(aspectClass)) {
          Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
          if (advisor != null) {
             advisors.add(advisor);
          }
       }

       // If it's a per target aspect, emit the dummy instantiating aspect.
       if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
          Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
          advisors.add(0, instantiationAdvisor);
       }

       // Find introduction fields.
       for (Field field : aspectClass.getDeclaredFields()) {
          Advisor advisor = getDeclareParentsAdvisor(field);
          if (advisor != null) {
             advisors.add(advisor);
          }
       }

       return advisors;
    }

我们看下获取aop类型上面所有的方法的函数

    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
       final List<Method> methods = new LinkedList<>();
       ReflectionUtils.doWithMethods(aspectClass, method -> {
          //这里就是获取被@Aspect注解修饰类上面的所有方法去掉Pointcut注解修饰的方法
          if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
             methods.add(method);
          }
       });
       methods.sort(METHOD_COMPARATOR);
       return methods;
    }

下面我们看下根据类对象和方法对象获取通知的方法

    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
          int declarationOrderInAspect, String aspectName) {

       validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
       //这里更加类对象和方法获取上面注解封装为AspectJExpressionPointcut对象
       AspectJExpressionPointcut expressionPointcut = getPointcut(
             candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
       if (expressionPointcut == null) {
          return null;
       }
       //封装成InstantionModelAwarePointcutAdvisorImpl
       return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
             this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

下面我们进一步进入到封装成AspectJExpressionPointcut方法里面去

    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
      //从候选方法上面获取AspectAnnotation注解
       AspectJAnnotation<?> aspectJAnnotation =
             AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
       if (aspectJAnnotation == null) {
          return null;
       }
     //封装为AspectJExpressionPointcut对象
       AspectJExpressionPointcut ajexp =
             new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
      //设置pointcut字符串表达式
       ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
       if (this.beanFactory != null) {
          ajexp.setBeanFactory(this.beanFactory);
       }
       return ajexp;
    }

我们再进入到findAspectJAnnotationOnMethod方法里面去

    protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
       Class<?>[] classesToLookFor = new Class<?>[] {
             Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
       for (Class<?> c : classesToLookFor) {
          AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
          if (foundAnnotation != null) {
             return foundAnnotation;
          }
       }
       return null;
    }

上面就是在获取方法上面含有Before,Aroud,After,AfterReturning,AfterThrowing,Pointcut方法

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring中aop的源码解析(三)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏