<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      創建目標類的代理對象過程

      步驟1

      finishBeanFactoryInitialization(beanFactory), 完成BeanFactory的初始化工作,就是來創建剩下的單實例bean,

      在創建的過程中就會被各個后置處理器攔截掉,下面我們就看看finishBeanFactoryInitialization(beanFactory);


      步驟2

      進入到 finishBeanFactoryInitialization(beanFactory)中,就會看到來到 beanFactory.preInstantiateSingletons()創建bean

      進入preInstantiateSingletons()方法中,看到在循環所有bean創建對象,通過getBean(beanName)創建

      最后來到doGetBean(name, null, null, false)方法,首先檢查單實例的緩存中是否存在當前對象

      如果存在就直接返回,否則就通過調用 getSingleton()獲得單實例bean,只要創建好的bean就會被緩存起來,保證單實例bean

      之后調用createBean(beanName,mbd,args)創建bean

      進入到createBean()后就會調用resolveBeforeInstantiation(beanName, mbdToUse)方法,


      希望后置處理器再此能返回一個代理對象,如果能返回就是使用,否則就調用下面的doCreateBean()創建,對于doCreateBean()方法之前已經詳細介紹過了,


      就是先創建bean實例,然后為bean屬性賦值,然后在調用bean的init方法前后調用后置處理器等等操作。

      我們來到 resolveBeforeInstantiation(beanName, mbdToUse)中, 給目標對象一個創建一個代理的機會

      protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
          Object bean = null;
          // 檢查是否尚未確定不需要在實例化前解析
          if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
              // 確保此時 bean 類已經被解析
              // 如果不是合成 bean 且存在 InstantiationAwareBeanPostProcessor
              if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                  // 確定目標 bean 的類型
                  Class<?> targetType = determineTargetType(beanName, mbd);
                  if (targetType != null) {
                      // 應用實例化前的 BeanPostProcessor
                      bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                      if (bean != null) {
                          // 如果成功創建了 bean,則應用初始化后的處理器
                          bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                      }
                  }
              }
              // 標記是否成功在實例化前解析了 bean
              mbd.beforeInstantiationResolved = (bean != null);
          }
          return bean;
      }
      

      先調用 applyBeanPostProcessorsBeforeInstantiation(targetType, beanName)方法,進入其中,看到

      先循環所有后置處理器,判斷是不是InstantiationAwareBeanPostProcessor類型的后置處理器,


      如果是就調用它的postProcessBeforeInstantiation(beanClass, beanName)方法,


      而我們之前已經說過AnnotationAwareAspectJAutoProxyCreatorSmartInstantiationAwareBeanPostProcessor類型的后置處理器,


      SmartInstantiationAwareBeanPostProcessor又繼承了InstantiationAwareBeanPostProcessor


      所以AnnotationAwareAspectJAutoProxyCreator也就是InstantiationAwareBeanPostProcessor這種類型的后置處理器,


      最后就會調用AnnotationAwareAspectJAutoProxyCreatorpostProcessBeforeInstantiation()方法,


      我們就來看看postProcessBeforeInstantiation()方法都干了些啥?


      步驟3

      現在我們就關心我們自己創建的LogAspect和MathCal是怎樣創建的?我們的MathCal來到


      org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(Class<?>, String)方法


      (AnnotationAwareAspectJAutoProxyCreator中沒有postProcessBeforeInstantiation()方法的實現,只能調用父類的方法),


      首先判斷是否在advisedBeans中,advisedBeans中保存了所有需要增強的目標對象bean。第一次創建是不會包含的,所有 if 沒進去。

      然后就來到第二個判斷,首先判斷當前bean是否是基礎類型即判斷是否是實現了Advice,Pointcut,Advisor,AopInfrastructureBean

      這幾個接口,其次還會判斷是否是加了@Aspect注解的

      最后再通過shouldSkip(beanClass, beanName)判斷是否需要跳過

      /**
       * 判斷是否應該跳過對指定 Bean 類和 Bean 名稱的處理。
       *
       * @param beanClass Bean 的類對象
       * @param beanName  Bean 的名稱
       * @return 如果應該跳過處理則返回 true,否則返回 false
       */
      protected boolean shouldSkip(Class<?> beanClass, String beanName) {
          // 待辦事項:考慮通過緩存切面名稱列表來進行優化
          // 查找所有候選的 Advisor(通知器)
          List<Advisor> candidateAdvisors = findCandidateAdvisors();
          // 遍歷所有候選的 Advisor
          for (Advisor advisor : candidateAdvisors) {
              // 檢查當前 Advisor 是否為 AspectJ 切點通知器
              if (advisor instanceof AspectJPointcutAdvisor) {
                  // 獲取該 Advisor 中的通知,并將其轉換為 AbstractAspectJAdvice 類型
                  // 然后獲取切面的名稱,并與當前 Bean 的名稱進行比較
                  if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
                      // 如果切面名稱與 Bean 名稱相等,則表示應該跳過對該 Bean 的處理
                      return true;
                  }
              }
          }
          // 如果沒有匹配到需要跳過的情況,則調用父類的 shouldSkip 方法進行判斷
          return super.shouldSkip(beanClass, beanName);
      }
      

      在shouldSkip()中首先獲得四個增強器即切面中的四個通知方法,將通知方法包裝為InstantiationModelAwarePointcutAdvisor類型的,


      判斷增強器是否是AspectJPointcutAdvisor類型的,而我們的類型不是,就會調用父類的super.shouldSkip(beanClass, beanName);


      返回false,最后就返回null,繼續 doCreateBean(beanName, mbdToUse, args)-->createBeanInstance(beanName, mbd, args)

      -->populateBean(beanName, mbd, instanceWrapper)-->initializeBean(beanName, exposedObject, mbd)-->applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)


      之后又來到org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(Object, String)方法

      調用 wrapIfNecessary(bean, beanName, cacheKey) 進入其中

        /**
         * 如果有必要,對指定的 Bean 進行包裝(創建代理)。
         *
         * @param bean     要檢查并可能包裝的 Bean 實例
         * @param beanName Bean 的名稱
         * @param cacheKey 用于緩存的鍵,代表當前 Bean 的唯一標識
         * @return 如果需要,返回包裝后的代理對象;否則返回原始的 Bean 實例
         */
        protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
            // 檢查 beanName 是否不為空,并且 targetSourcedBeans 集合中包含該 beanName
            // 如果是,則表示該 Bean 已經由 TargetSource 處理過,不需要再進行包裝,直接返回原始 Bean
            if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
                return bean;
            }
            // 從 advisedBeans 緩存中獲取當前 Bean 對應的處理標記
            // 如果標記為 false,表示該 Bean 不需要被代理,直接返回原始 Bean
            if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
                return bean;
            }
            // 檢查該 Bean 的類是否為基礎設施類(如 Spring 內部使用的類),或者是否應該跳過該 Bean 的處理
            // 如果是,則將該 Bean 的處理標記為 false 并放入 advisedBeans 緩存中,然后返回原始 Bean
            if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return bean;
            }
      
            // 如果存在通知(Advice),則創建代理
            // 獲取該 Bean 對應的通知和通知器數組
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
            // 如果獲取到的通知和通知器數組不為 DO_NOT_PROXY(表示需要進行代理)
            if (specificInterceptors != DO_NOT_PROXY) {
                // 將該 Bean 的處理標記為 true 并放入 advisedBeans 緩存中
                this.advisedBeans.put(cacheKey, Boolean.TRUE);
                // 創建代理對象
                Object proxy = createProxy(
                        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
                // 將代理對象的類型放入 proxyTypes 緩存中
                this.proxyTypes.put(cacheKey, proxy.getClass());
                // 返回代理對象
                return proxy;
            }
      
            // 如果不需要進行代理,將該 Bean 的處理標記為 false 并放入 advisedBeans 緩存中
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            // 返回原始 Bean
            return bean;
        }
      

      獲取所有候選增強器,然后通過切點表達式進行篩選,獲得與其當前匹配的bean增強器(通知方法),如何獲取呢?

      通過 createProxy() 創建代理對象,最后保存當前bean到 advisedBeans中,表示當前bean已經增強

      先根據 Bean 名稱獲取其對應的增強器(通知方法),保存到proxyFactory中,通過proxyFactory.getProxy(getProxyClassLoader()),獲得代理對象

        /**
         * 創建指定 Bean 的代理對象。
         *
         * @param beanClass         Bean 的類對象,即要被代理的目標類
         * @param beanName          Bean 的名稱,用于標識該 Bean
         * @param specificInterceptors 該 Bean 對應的特定攔截器和通知器數組
         * @param targetSource      目標對象的源,用于獲取實際的目標對象
         * @return 創建好的代理對象
         */
        protected Object createProxy(
                Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
      
            // 檢查當前的 Bean 工廠是否為 ConfigurableListableBeanFactory 類型
            if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
                // 如果是,則通過 AutoProxyUtils 工具類暴露目標類信息到 Bean 工廠中
                // 這有助于在某些情況下讓其他組件知道目標類的實際類型
                AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
            }
      
            // 創建一個 ProxyFactory 實例,用于創建代理對象
            ProxyFactory proxyFactory = new ProxyFactory();
            // 將當前對象的配置信息復制到 ProxyFactory 中
            // 確保代理工廠使用相同的配置
            proxyFactory.copyFrom(this);
      
            // 檢查 ProxyFactory 是否已經配置為代理目標類(使用 CGLIB 代理)
            if (!proxyFactory.isProxyTargetClass()) {
                // 如果沒有配置為代理目標類,則檢查是否應該代理目標類
                if (shouldProxyTargetClass(beanClass, beanName)) {
                    // 如果應該代理目標類,則將 ProxyFactory 的配置設置為代理目標類
                    proxyFactory.setProxyTargetClass(true);
                } else {
                    // 否則,評估目標類實現的接口,根據接口情況來配置代理方式
                    evaluateProxyInterfaces(beanClass, proxyFactory);
                }
            }
      
            // 根據 Bean 名稱獲取其對應的增強器
            Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
      
            // 將構建好的增強器添加到 ProxyFactory 中
            proxyFactory.addAdvisors(advisors);
      
            // 設置目標對象(被代理對象)
            proxyFactory.setTargetSource(targetSource);
      
            // 對 ProxyFactory 進行自定義配置,允許子類進行額外的定制
            customizeProxyFactory(proxyFactory);
      
            // 設置 ProxyFactory 是否凍結代理配置
            // 如果凍結,則在創建代理后不能再修改代理的配置
            proxyFactory.setFrozen(this.freezeProxy);
            // 檢查通知器是否已經預先過濾
            if (advisorsPreFiltered()) {
                // 如果已經預先過濾,則設置 ProxyFactory 為預過濾狀態
                proxyFactory.setPreFiltered(true);
            }
      
            // 使用 ProxyFactory 創建代理對象,并指定代理類加載器
            return proxyFactory.getProxy(getProxyClassLoader());
        }
      

      進入其中

        /**
         * 根據提供的 AOP 配置信息創建 AOP 代理對象。
         *
         * @param config 包含 AOP 代理配置的 AdvisedSupport 對象
         * @return 一個 AopProxy 實例,用于生成具體的 AOP 代理對象
         * @throws AopConfigException 如果配置信息不符合代理創建要求,拋出此異常
         */
        public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
            // 檢查是否滿足使用 CGLIB 代理的條件:
            // 1. 是否開啟了優化選項
            // 2. 是否明確指定使用目標類代理
            // 3. 是否沒有用戶提供的代理接口
            if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
                // 獲取目標類的 Class 對象
                Class<?> targetClass = config.getTargetClass();
                // 如果目標類為 null,說明無法確定目標類,拋出 AopConfigException 異常
                if (targetClass == null) {
                    throw new AopConfigException("TargetSource cannot determine target class: " +
                            "Either an interface or a target is required for proxy creation.");
                }
                // 如果目標類是接口或者是代理類,使用 JDK 動態代理
                if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
                    return new JdkDynamicAopProxy(config);
                }
                // 否則,使用 ObjenesisCglibAopProxy(基于 CGLIB 的代理)
                return new ObjenesisCglibAopProxy(config);
            } else {
                // 如果不滿足使用 CGLIB 代理的條件,默認使用 JDK 動態代理
                return new JdkDynamicAopProxy(config);
            }
        }
      

      spring自動決定使用JDK方式代理還是使用Cglib方式代理

      至此就創建出代理對象啦,并返回回去了,以后容器中拿到的就是代理對象了,接下來拿到代理對象,如何調用增強方法

      posted @ 2025-03-25 23:52  jock_javaEE  閱讀(20)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲一区二区三午夜福利| 亚洲一级特黄大片在线观看| 在线观看精品日本一区二| 91密桃精品国产91久久| 精品国产成人国产在线观看| 久久久亚洲欧洲日产国码αv| 国产美女被遭强高潮免费一视频| 欧美午夜精品久久久久久浪潮| 一区二区三区四区五区自拍| 玩弄丰满少妇人妻视频| 午夜国产小视频| 国产超碰无码最新上传| 亚洲av色夜色精品一区| 亚洲日本va午夜在线影院| 男女性高爱潮免费网站| 中国性欧美videofree精品| 2020年最新国产精品正在播放 | 亚洲欧洲日产国码无码久久99 | 日韩精品一区二区三区视频| 国产乱人伦真实精品视频| 国产高清精品在线一区二区| 亚洲国产精品一区二区视频| 国产精品中文字幕视频| 免费看欧美日韩一区二区三区 | 九色综合国产一区二区三区| 亚洲人成网站在线播放2019| 2019国产精品青青草原| 亚洲少妇一区二区三区老| 国内精品视频一区二区三区八戒| 少妇人妻偷人一区二区| 国产一区二区三区我不卡| 久久精品国产99国产精品严洲 | 人妻系列无码专区无码中出| 国产情侣激情在线对白| 易门县| 日韩本精品一区二区三区| 少妇人妻偷人偷人精品| 国产综合内射日韩久| 亚洲av第二区国产精品| 国产精品福利中文字幕| 人人澡人人透人人爽|