1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Spring Aop初始化源碼分析

        共 27517字,需瀏覽 56分鐘

         ·

        2021-03-26 08:37

        點擊上方藍色字體,選擇“標星公眾號”

        優(yōu)質(zhì)文章,第一時間送達

        1 工程簡介


        1.1 pom

        <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
                <spring.version>5.2.8.RELEASE</spring.version>
            </properties>

            <dependencies>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>4.13</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${spring.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                    <version>1.16.20</version>
                </dependency>
                <!-- 日志相關依賴 -->
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                    <version>1.7.10</version>
                </dependency>
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                    <version>1.1.2</version>
                </dependency>
                <dependency>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-core</artifactId>
                    <version>1.1.2</version>
                </dependency>

                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                    <version>${spring.version}</version>
                </dependency>
            </dependencies>

        1.2 AopConfig

        @Configuration
        @EnableAspectJAutoProxy
        @Aspect
        public class AopConfig {

            /**
             * 聲明切點
             */
            @Pointcut("execution(* com.rosh.service.*.*(..))")
            public void pointCut() {

            }

            @Around("pointCut()")
            public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
                System.out.println("==============調(diào)用前=================");
                Object proceed = proceedingJoinPoint.proceed();
                System.out.println("==============調(diào)用后=================");
                return proceed;
            }


        }


        1.3 StudentService

        @Service
        public class StudentService {

            public void addStudent() {
                System.out.println("添加學生");
            }


        }


        1.4 RoshTest

        public class RoshTest {

            @Test
            public void mainTest(){

                AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.rosh");

                StudentService studentService = (StudentService) applicationContext.getBean("studentService");

                studentService.addStudent();

            }

        }


        1.5 運行結果


        2 @EnableAspectJAutoProxy作用

        描述:開啟Spring AOP功能。


        (1) IOC中加入AspectJAutoProxyRegistrar.class

        (2) 注冊 AnnotationAwareAspectJAutoProxyCreator.class

        3 AnnotationAwareAspectJAutoProxyCreator.class 源碼分析

        描述:該類是AOP核心類。該類實現(xiàn)了BeanPostProcessor接口,說明在bean初始化時,進行后置加強。

        該類作用是,當bean初始化時,被該類后置加強:

        (1) 查找有效的advisor列表。(advisor=advice+pointCut)
        (2) 匹配當前bean,是否在pointCut表達式范圍,匹配方法是否需要加強,把匹配到的advisor列表返回。
        (3) 根據(jù)有效的advisor列表創(chuàng)建代理對象、 


        3.1 后置加強邏輯

        @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;
         }

        3.2 wrapIfNecessary方法

        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.
          /**
           * 【1】獲取當前bean有效的Advisor,Advisor = advice + pointCut
           */
          Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

          if (specificInterceptors != DO_NOT_PROXY) {
           this.advisedBeans.put(cacheKey, Boolean.TRUE);

           /**
            * 【2】創(chuàng)建代理對象
            */
           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;
         }

        3.3 getAdvicesAndAdvisorsForBean 方法解析

            @Override
         @Nullable
         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();
         }

        描述:該方法獲取有效的Advisor,主要作用,發(fā)現(xiàn)所有的advisor其次匹配當前bean。

        protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {

          /**
           * 【1】找到工程中所有Advisor(解析帶有@Aspect注解類生成Advisor對象)
           */
          List<Advisor> candidateAdvisors = findCandidateAdvisors();

          /**
           * 【2】 匹配當前類
           */
          List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
          extendAdvisors(eligibleAdvisors);
          if (!eligibleAdvisors.isEmpty()) {
           eligibleAdvisors = sortAdvisors(eligibleAdvisors);
          }
          return eligibleAdvisors;
         }

        3.3.1 findCandidateAdvisors

        作用:查找所有的advisor。

        @Override
         protected List<Advisor> findCandidateAdvisors() {
          // Add all the Spring advisors found according to superclass rules.
          //找到所有的Advisor
          List<Advisor> advisors = super.findCandidateAdvisors();
          // Build Advisors for all AspectJ aspects in the bean factory.

          /**
           * 創(chuàng)建候選切面 對@Aspect注解進行處理
           */
          if (this.aspectJAdvisorsBuilder != null) {
           advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
          }
          return advisors;
         }

        核心方法:buildAspectJAdvisors()

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

          if (aspectNames == null) {
           synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
             List<Advisor> advisors = new ArrayList<>();
             aspectNames = new ArrayList<>();

             /**
              * 從spring 中獲取所有的類
              */
             String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
               this.beanFactory, Object.class, truefalse);
             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.

              /**
               *  獲取beanName 的class
               */
              Class<?> beanType = this.beanFactory.getType(beanName);
              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) {

                //創(chuàng)建獲取有@Aspect注解類的實例工廠,負責獲取有@Aspect注解的實例
                MetadataAwareAspectInstanceFactory factory =
                  new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

                //創(chuàng)建切面Advisor對象
                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 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;
         }

        3.3.2 findAdvisorsThatCanApply

        描述:用所有advisor匹配當前class獲取當前類有效的advisor列表。

        protected List<Advisor> findAdvisorsThatCanApply(
           List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

          ProxyCreationContext.setCurrentProxiedBeanName(beanName);
          try {
           /**
            * 判斷當前類是否在這些切面的pointCut中
            */
           return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
          }
          finally {
           ProxyCreationContext.setCurrentProxiedBeanName(null);
          }
         }

        描述:找到有效的Advisor后匹配當前bean是否需要加強

        public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
          if (candidateAdvisors.isEmpty()) {
           return candidateAdvisors;
          }
          List<Advisor> eligibleAdvisors = new ArrayList<>();
          for (Advisor candidate : candidateAdvisors) {
           if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
            eligibleAdvisors.add(candidate);
           }
          }
          boolean hasIntroductions = !eligibleAdvisors.isEmpty();

          /**
           * 匹配
           */
          for (Advisor candidate : candidateAdvisors) {
           if (candidate instanceof IntroductionAdvisor) {
            // already processed
            continue;
           }

           /**
            * 判斷當前類、方法是否匹配PointCut,如果匹配,把有效切面存入eligibleAdvisors
            */
           if (canApply(candidate, clazz, hasIntroductions)) {
            eligibleAdvisors.add(candidate);
           }
          }
          return eligibleAdvisors;
         }


        描述:真正匹配方法,判斷當前類是否在pointCut表達式中,在匹配當前方法是否需要加強。

        public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
          Assert.notNull(pc, "Pointcut must not be null");

          /**
           * 【1】判斷當前類是否匹配Pointcut
           */
          if (!pc.getClassFilter().matches(targetClass)) {
           return false;
          }

          MethodMatcher methodMatcher = pc.getMethodMatcher();
          if (methodMatcher == MethodMatcher.TRUE) {
           // No need to iterate the methods if we're matching any method anyway...
           return true;
          }

          IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
          if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
           introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
          }

          Set<Class<?>> classes = new LinkedHashSet<>();
          if (!Proxy.isProxyClass(targetClass)) {
           classes.add(ClassUtils.getUserClass(targetClass));
          }
          classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

          /**
           * 【2】 判斷類中方法是否匹配
           */
          for (Class<?> clazz : classes) {
           Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
           for (Method method : methods) {
            if (introductionAwareMethodMatcher != null ?
              introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
              methodMatcher.matches(method, targetClass)) {
             return true;
            }
           }
          }

          return false;
         }

        4 buildAspectJAdvisors() 方法debug

        描述:該方法是獲取當前項目中所有advisor。一個advisor由pointCut和advice組成,代表一個切面。

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

          if (aspectNames == null) {
           synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
             List<Advisor> advisors = new ArrayList<>();
             aspectNames = new ArrayList<>();

             /**
              * 從spring 中獲取所有的類
              */
             String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
               this.beanFactory, Object.class, truefalse);
             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.

              /**
               *  獲取beanName 的class
               */
              Class<?> beanType = this.beanFactory.getType(beanName);
              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) {

                //創(chuàng)建獲取有@Aspect注解類的實例工廠,負責獲取有@Aspect注解的實例
                MetadataAwareAspectInstanceFactory factory =
                  new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

                //創(chuàng)建切面Advisor對象
                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 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;
         }

        描述:創(chuàng)建pointCut對象


        描述:創(chuàng)建advisor對象,傳入?yún)?shù)pointCut。advisor創(chuàng)建時,會創(chuàng)建內(nèi)部advice對象。

        描述:創(chuàng)建advice

        5 匹配流程debug

        描述:匹配類,切點進入當前類,在matches方法中,會把切點轉(zhuǎn)成表達式。

        描述:如果類、方法都匹配advisor,那么當前advisor可以加強當前bean

        ————————————————

        版權聲明:本文為CSDN博主「你攜秋月攬星河丶」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

        原文鏈接:

        https://blog.csdn.net/qq_34125999/article/details/115057552





        粉絲福利:Java從入門到入土學習路線圖

        ??????

        ??長按上方微信二維碼 2 秒


        感謝點贊支持下哈 

        瀏覽 52
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲乱伦小说网 | 熟女偷窥| 日韩中文字幕人妻 | 国内在线一区 | 色噜噜狠狠色综合影视 | 狠狠干性爱视频 | 懂色av蜜臀av粉嫩av分享吧 | 亚洲三级一区二区 | 亚洲精品一区二区三区婷婷月 | 欧美日韩美女视频 |