Spring源碼深度解析(容器方面)


1.1 IoC原理

​ 業務邏輯需要多個對象合作來實現,這樣多個對象之間就存在依賴關系。控制反轉把應用從復雜的對象依賴關系中解放出來,將依賴關系交給IoC容器管理(具體地就是將新建對象、為對象引用賦值等操作交給容器完成)。

1.2 IoC容器設計與實現:BeanFactory與ApplicationContext

1.實現BeanFactory的簡單容器系列--實現了容器的最基本功能。

2.ApplicationContext應用上下文,在1的基礎上,增加了許多面向框架的特性以及對應用環境的適配。

3.BeanDefinition抽象了對Bean的定義,用於管理對象和對象之間的依賴關系,是容器實現依賴反轉的核心數據結構。

1.2.1 容器的設計

1.BeanFactory接口

2.BeanFactory設計原理(以XmlBeanFactory為例)

DefaultListableBeanFactory是默認的完整容器功能實現類,XMLBeanFactory繼承該類並添加讀取XML配置文件的功能。

編程式使用:

3.ApplicationContext

面向框架的使用風格

4.ApplicatioinContext設計原理(以FileSystemXmlApplicationContext為例)

1.2.3 IoC容器初始化過程(以FileSystemXmlApplicationContext為例)

IoC容器的初始化包括 BeanDefinition的定義、載入和注冊三個過程(即1.2.1.2種函數式使用IoC),被封裝在refresh()方法中。

  1. Resource定位:定位BeanDefinition資源的位置。

  2. BeanDefinition的載入:把上一步定位的資源載入,並轉變為IoC容器內部的數據結構,即BeanDefinition(POJO對象在IoC容器中的抽象)。

  3. 向IoC容器注冊這些BeanDefinition(到一個HashMap),具體是調用BeanDefinitionRegistry接口。

 

注意:這個過程並不包括依賴注入;依賴注入一般發生在第一次調用getBean時,但可以通過Bean的lazyinit屬性調控。

下面具體講這三個過程。

1.3 IoC詳細初始化過程

1.3.1 BeaDefinition的Resource定位

在FileSystemXmlApplicationContext的構造函數中,refresh()啟動容器初始化。

refresh(){
  refreshBeanFactory(){
1.關閉可能存在的BeanFactory
2.createBeanFactory(){}
3.loadBeanDefinitions(BeanFacotory){
//定位BeanDefinition的兩種方式
1.ResourcePatternResolver.getResource()
2.getResource(){
1.CLASSPATH: new ClassPathResource()
2.URL: getResourceByPath()
}
}
        //載入
           3.Reader(BeanFactory);
           //交給具體的reader,載入BeanDefinitions。
              //配置reader
           4.loadBeanDefinitions(Reader){
          1.getConfigResources();//返回Resources【】或者String[]
               2.reader.loadBeanDefinitions( Resources[]){
                   1.reader.loadBeanDefinition( Resources[i]){
                       1. loadBeanDefinitions( EncodedResource(resource)){
                           //創建InputSource並設置字符集
                           1.InputSource inputsource = new inputSource(
                          encodeResource.getResource().getInputStream()
                          ).setEncoding(encodeResource.getEncoding());
                           //真正載入
                           2.doLoadBeanDefinitions( inputsource,encodeResource.getResource){
                               //加載前的准備工作
                               //交給DocumentReader去讀取
                               1.registerBeanDefinitions(doc, resource){
                                   1.documentReader = createBeanDefinitionDocumentReader();
                                   //先完成通用xml解析,再按照Bean規則解析。
                                   2.documentReader.registerBeanDefinitoins(doc,                                                                                       createContext(resource)){
                                       //真正加載、解析
                                       doRegisterBeanDefinitoins(Element  root){
                                           parseBeanDefinitions(){
                                               //默認標簽
                                               1.parseDefaultElement(){                          
                                            //包含了對beans、bean、alias、import標簽的解析,以bean為例子
                                                   processBeanDefinition(){
                                                       //解析
                                                       parseBeanDefinitionElement(){};
                                                       //注冊
                                                       registerBeanDefinition(){};
                                                       //通知相關監聽器
                                                       fireComponentRegistered();
                                                  };
                                             
                                      };
                                               //自定義標簽
                                               2.parseCustomElemtn();
                                      };
                                      };
                                       
                                  };
                              }
                          };
                      };
                       
                  }
              };           }  // } }}/* 1.refresh  2.refreshBeanFactory 2.1 關閉可能存在的BeanFactory 2.1 createBeanFactory(){} 3.loadBeanDefinitions(BeanFacotory) 3.1定位BeanDefinition的兩種方式 //載入            3.2 Reader(BeanFactory);//關聯reader和beanFactory            4.loadBeanDefinitions(Reader)           4.1 獲取資源           5.reader.loadBeanDefinitions( Resources[])           5.1 設置字符集           5.2 取得XML的inputSource           6.doLoadBeanDefinitions( inputsource,encodeResource.getResource)           6.1 解析XML-->document           7.registerBeanDefinitions(doc, resource)           7.1 創建DocumentReader           8. documentReader.registerBeanDefinitoins()           9. doRegisterBeanDefinitoins(Element root)           10. parseBeanDefinitions(){ //真正解析,針對不同標簽解析、注冊、通知監聽器           //默認標簽                                                1.parseDefaultElement(){                                                                       //包含了對beans、bean、alias、import標簽的解析,以bean為例子                                                    processBeanDefinition(){                                                        //解析                                                        parseBeanDefinitionElement(){};                                                        //注冊                                                        registerBeanDefinition(){};                                                        //通知相關監聽器                                                        fireComponentRegistered();                                                    };                                                                                     };                                                //自定義標簽                                                2.parseCustomElemtn();}                     */

1.3.2 BeanDefinition的載入和解析

把定義的BeanDefinition轉為IoC容器內部數據結構(HashMap)。

可以看到調用是從最上層的AbstractApplicaitonContext一步步往繼承樹子節點走。

  1. refresh()//AbstractApplicaitonContext

  2. refreshBeanFactory(){ //AbstractRefreshableApplicationContext

    createBeanFactory-->DefaultListableBeanFactory

    loadBeanDefinitions-->具體的實現的Reader

    }

    //處理默認標簽--parseDefaultElemnt()包含 import,beans,bean,alias標簽,下面只是bean標簽
    processBeanDefinition(Element ele, BeanDefinitionParseDelegate delegate){
       1.delegate.parseBeanDefinitionElement(Elemnt , BeanDefinition ){
           1.1提取id和name,解析beanName,parseBeanDefinitionElement(Element, BeanName, BeanDefinition){
               1.1.1 提取class和parent,創建GenericBeanBeanDefinition(className, parent);
               1.1.2 解析bean屬性
               1.1.3 解析bean的子元素屬性,包括:Meta,LookupOverrideSubElement,ReplaceMethodsSubElement
              ConstructorArgElements,PropertyElements,QualifierElements
          };    
           return BeanDefinitionHolder(BeanDefinition, beanName, aliasesArray);
      };
       
       //解析默認標簽中的自定義標簽
       2.delegate.decorateBeanDefinitionIfRequired();
       //注冊
       3.BeanDefinitionReaderUtils.registerBeanDefinition(BeanDefinitionHolder BeanDefinitionRegistry{
           3.1 使用beanName做唯一注冊標識
               registry.registerBeanDenifition(beanName, BeanDefinition);
           3.2 注冊所有別名
               registry.registerBeanDenifition(beanName, alias);
      };
       4.getReaderContext().fireComponentRegistered(); //為擴展保留
    }
                                                         
    //處理默認標簽--parseDefaultElemnt()包含 import,beans,bean,alias標簽,下面只是alias標簽              
    processAliasRegisteration(){
    1.提取BeanName和alias,都不可空,否則拋出異常
       2.getReaderContext().getRegistery().registerAlias(name, alias);                                 }                        
                                                         
    //處理默認標簽--parseDefaultElemnt()包含 import,beans,bean,alias標簽,下面只是import標簽
                                                         
    嵌入式Beans,遞歸解析beans。                                                      

  3. parseBeanDefinitionElement() //解析

    BeanDefinition只是一些靜態配置信息,需要完成數據向容器的注冊,才能完全發揮容器的作用。

1.3.3 BeanDefinition在容器的注冊

1.private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

將BeanName作為鍵, BeanDefinition作為值保存。

2.

1.4 依賴注入(Bean的加載)

<u>依賴注入是用戶第一次向容器申請Bean時觸發(例外:lazy-init,可以控制Bean的預實例化)。</u>

FactoryBean

一般Spring利用反射機制通過bean的class屬性實現bean。這樣比較復雜,在<bean>配置大量信息。可以通過實現FactoryBean接口,在getObject方法中來定制實例化bean的邏輯。另外,該FactoryBean的getBean方法返回的不是FactoryBean(“&beanname”這樣取得)而是getObejct方法的bean。

1.4.1 實例化過程

getBean(){
doGetBean(){
     1.//提取beanName
     2.嘗試從緩存或者實例工廠獲取bean,取得的bean是原始狀態,還需要getObjectForBeanInstance
         getSingleton(beanName, true//允許早期依賴);
     3. 緩存沒有,則新創建。
         3.1 原型模式的循環依賴檢測
         3.2 當XML中沒有bean的配置時,去parentBeanFactory尋找
         3.3 取得BeanDefinition后,轉為RootBeanDefinition
         3.4 存在依賴Bean,遞歸調用
         3.5 根據Scope創建bean
               每種scope,實際都是以下方法:
        3.5.1 createBean();
        3.5.2 getObjectForBeanInstance();
};
};

1、緩存中獲取

getSingleton(beanName, true//允許早期依賴);
1.檢測singletonObjects();獲得bean則返回// map存放beanName和beanInstance
2.上一步沒有獲得bean,檢測earlySingletonObjects();獲得bean則返回//map存放還在創建過程中的bean,循環檢測
3.前兩步都沒有獲得bean,且允許早期依賴,從singletonFactories中獲取ObjectFactory初始化策略,初始化bean

4.取得bean,
 調用getObjectForBeanInstance{
1.檢測是否是FactoryBean,
2.否直接返回bean,
   3.是調用getObjectFromFacrotyBean(beanName){
  1.檢測單例
  2.doGetObjectFromFacrotyBean(){
  1.檢測權限
      2.factory.getObject();
      //ObjectFactoryBean的后處理器--AbstractAutowireCapableBeanFactory
      3.postProcessObjectFromFactoryBean();
      //盡可能保證在Bean初始化后,都會調用注冊的BeanPostProcessor的postProcessAfterInitialization方法
  };
  };
4.返回getObject方法的結果。
}
若這三步都沒有獲得,則需要新建。

2、獲取單例(創建緩存中不存在的單例)

getSingleton(beanName, singletonFactory){
在singletonObjects上加鎖
  1.緩存檢測,/*構造器循環依賴無法解決。setter循環依賴通過,提取暴露一個工廠方法,並將在當前創建bean池該bean的標識符,提供還未創建完成的Bean。
*/
       2.beforeSingletonCreaton();//記錄正在創建的狀態
  3.singletonFactory.getObject(){
            1.createBean(beanName, mbd, args){
  };
  4.afterSingleCreation();   //刪除正在創建的狀態
  5.addSingleton(beanName, singletonObject);//創建好的bean加入緩存,並刪除各種輔助狀態
}

createBean(beanName, mbd, args){
   解析class
   1.mbd.prepareMethodOverrides();//驗證並准備覆蓋的方法,主要是lookup-method和replace-method屬性。
   2.Object bean = resolveBeforeInstantiation(beanName, mbd){//對Bean的屬性做些前置處理
       bean = applyBeanPostProcessorsBeforeInstantiation(){
           bean=applyBeanPostProcessorBeforeInstantiation();
           if(bean!=null) applyBeanPostProcessorAfterInstantiation();
      };//實例化前后處理器應用
       if(bean!=null)
           applyBeanPostProcessorsAfterInitialization();//實例化后后處理器應用,滿足spring規則。
  };
   3.if(bean!=null) return bean;//短路測試
   4.doCreateBean(beanName, mbd, args){
       1.清除緩存?
       2.createBeanInstance(){
        1.resolveBeanClass //解析class
           2.非public類無法訪問,所以無法構建bean
           3.mbd中工廠方法不為空,調工廠創建。
               instantiateUsingFactoryMethod();
           4.解析構造函數並實例化,緩存在resolvedConstructorOrFactory中。
               5. autowireConstructor(){
               //太復雜,大致為
               確定參數(傳入了參數(用戶調用getBean可以傳入),緩存中參數,配置文件中參數)
                   確定構造函數
                   轉換參數類型和構造函數不確定性驗證--不太懂
                   根據實例化策略(instantiate)和構造函數和參數,實例化Bean
          };//構造函數自動注入
          instantiateBean();//默認構造函數,沒有參數直接根據實例化策略實例化Bean
         
           instantiate{//實例化策略
               if(beanDefinition.getMethodOverrides().isEmpty()) 直接反射
                   else 動態代理將覆蓋的方法織入
          }
         
      }; Bean的合並后處理
       3.依賴處理 addsingletonFactory() //單例,可循環依賴,當前Bean正在創建中,曝光工廠方法
       4.populateBean(){//屬性注入
           1.getPropertyValues//提取屬性
           2.根據BeanWraper和pvs是否為空,考慮注入
           3.  //提取依賴的Bean,放入PropertyValues中。
               autoWiredByName();
          autoWiredByType();//比較復雜,暫不了解
           4.postProcessPropertyValues();//填充屬性前對屬性再次處理。
           5.applyPropertyValues();//應用屬性到Bean中。         };        5.initializeBean(){//Bean配置里面的init-method屬性。前面已經執行了Bean的實例化和屬性填充,現在是調用            //用戶的初始化方法            1.invokeAwareMethods(){                判斷是BeanNameAware、BeanClassAware、還是BeanFactoryAware,分別傳入相應的Aware前面部分。                    //實現Aware的接口會取得一些資源           };            2.applyBeanPostProcessorsBeforeInitialization(){                postProcessBeforeInitialization();                           };            3.invokeInitMethods(){                先執行自定義Bean的initializingBean接口中afterPropertiesSet,                    然后是init-method方法。           };            4.applyBeanPostProcessorsAfterInitialization(){                postProcessAfterInitialization();           };         };        6.循環依賴檢測與處理        7.registerDisposableBeanIfNecessary(){         registerDispoableBean();//屬性配置destrot-method            //自定義的bean銷毀方法            registerDestructionCallback();       }//注冊DisposableBean銷毀方法並返回               };};​

1.5 ApplicatonContext

1.5.1 設置配置文件路徑

setConfigoLcations(String[] locations){
resolcePath();//解析路徑  
}

1.5.2 擴展功能

refresh(){
   1.prepareRefresh();
   2.beanFactory=obtainFreshBeanFactory();
   3.prepareBeanFactory(beanFactory);
   4.postProcessBeanFactory(beanFactory);
   5.invokeBeanFactoryPostProcessors(beanFactory);
   6.registerBeanPostProcessors(beanFactory);
   7.initMessageSource();
   8.initApplicationEventMulticaster();
   9.onRefresh();
   10.registerListeners();
   11.finishBeanFactoryInitializatioin(beanFactory);
   12.finishRefresh();
}

1.prepareRefresh(); 准備刷新上下文環境

prepareRefresh(){
   initPropertySources();//留給子類覆蓋,個性化地屬性處理和設置
   getEnviroment().validateRequiredProperties();
};

 

2.beanFactory=obtainFreshBeanFactory();初始化BeanFactory並進行XML文件的讀取

beanFactory=obtainFreshBeanFactory(){
   refreshBeanFactry(){
       1.關閉已有Beanfacory
       2.createBeanFactory();
       3.customizeBeanFactory(){
           //開始擴展基本的bean
           覆蓋,循環依賴,
           //注解方式注入的支持
           setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidatResolver());
      };//定制BeanFactory
       4.loadBeanDefinitions(beanFactory);
       5.保存至全局beanFactory
  };
};

 

3.prepareBeanFactory(beanFactory);對beanFactory功能填充.ApplicationContext

prepareBeanFactory(beanFactory){
//添加表達式語言處理器  
   setBeanExpressionResolver(new StandardBeanExpressionResolver()){  
  };  -->在屬性填充解析屬性值時,調用evaluateBeanDefinitionString(){
        this.beanExpressionResolver.evaluate();  
      }
   //添加屬性編輯器-->一些屬性的是自定義的類,spring無法識別
   addPropertyEditorRegistrar();
   //添加BeanPostProcessor
   addBeanPostProcessor(new ApplicationContextAwareProcessor(...)){
       該處理器會調用 postprocessBefore||AfterInitialization()
           invokeAwareInterfaces(){
          獲取一些資源
      };
       
  };
   //設置忽略自動裝配的接口-->在invokeAwareInterfaces中的資源的獲取是由應用獲取的,也就是說這些資源的依賴關系已經不再是容器管理。所以需要忽略。
   //設置幾個自動裝配的特殊規則-->注冊依賴
   //添加AspectJ的支持
   //添加默認系統環境的bean
   
};

 

4.postProcessBeanFactory(beanFactory);子類覆蓋方法額外處理

通過實現BeanFactoryPostFactory接口,BeanFactory會在實例化任何bean之前獲得配置信息,從而能夠正確解析bean描述文件的變量引用。

5.invokeBeanFactoryPostProcessors(beanFactory);激活各種BeanFactory處理器

6.registerBeanPostProcessors(beanFactory);注冊攔截Bean創建的Bean處理器。在bean實例化時調用。

//BeanFactory沒有實現后處理器的自動注冊,Application實現自動注冊
registerBeanPostProcessors(beanFactory){
   
};

 

7.initMessageSource();為上下文初始化Message源

8.initApplicationEventMulticaster();初始化應用消息廣播器,放入applicationEventMulticaster中

1.定義事件繼承ApplicationEvent
2.定義監聽器ApplicationListener
3.定義事件廣播器
initApplicationEventMulticaster(){
注冊事件廣播器
}
4.事件廣播器有下面方法
當spring產生事件時,會調用下面方法遍歷監聽器
public void multicastEvent(final ApplicationEvent event){
listener.onApplicationEvent(event);//每個監聽器都會獲取到事件,但是否處理,則是監聽器內部邏輯
}

9.onRefresh();initialize other special beans in specific context subclasses

10.registerListeners();查找Listener bean,注冊到消息廣播器中。

registerListeners(){
   //硬編碼方式
   for(Application<?> listener : getApplicationListeners()){
       getApplicationEventMulticaster().addApplicationListener(listener);
  }
   
   //配置文件注冊監聽器
   String[] litenerBeanNames = getBeanNmesForType(ApplicationListener.class,true,false);
   for(String lisName:listenerBeanNames){
       getApplicationEventMulticaster().addApplicationListeer(lisName);
  }
}

 

11.finishBeanFactoryInitializatioin(beanFactory);初始化剩下的單實例(非惰性)

finishBeanFactoryInitializatioin(beanFactory){
   1.ConversionService的設置
    注冊在配置文件中的轉換器,conversionServic,該 Bean中包含轉換器,用於類型轉換。
       Converter<?class, ?class>比如前面的Converter<String, Date>//轉換器
           
   2.凍結所有bean的定義,再不能被修改或者進一步處理。
           freezeConfiguration();
   3.ApplicationContext會在啟動時將所有單例bean提前實例化,便於在啟動過程中發現配置中的錯誤,而不是在調用bean時才發現。
       preInstantiateSingletons(){}
};

 

12.finishRefresh();完成刷新,通知生命周期處理器lifecycleProcessor,發出ContextRefreshEvent通知別人

//spring提供LifeCycle接口,包含start/stop接口。分別在啟動和關閉時調用。
finishRefresh(){
   initLifecycleProcessor();
   gtLifecycleProcessor().onfresh();//啟動所有實現lifecyce的bean。
   //啟動完成后通過事件發布機制發布事件
   publishEvent(new ContextRefreshedEvent(this));
};

1.6 AOP

1.6.1 AopNamespaceHandler--AspectJ的解析器

public void init(){
   registerBeanDefinitionParser("aspect-autoprxy",new AspectJAutoProxyBeanDefinitionParser(){
       public BeabDefinition parse(Element, ParseContext){
           //注冊AnnotationAwareAspectJAutoProxyCreator
           registerAspectJAnnotationAutoProxyCreatorIfNecessary(Element, ParseContext){
               1.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
                   parserContext.getRegistry(),
              parserContext.extractSource(sourceElement)
              ){//自動注冊AnnotationAwareAspectJAutoProxyCreator(該類實現Aop功能)
                   return registerOrEscalateApcRequired(
                       AnnotationAwareAspectJAutoProxyCreator.calss,...){
                      //存在自動代理創建器,且與現在的不一致,需要根據優先級判斷。
                       在register中注冊代表自動創建器bean
                           return beandefinition;
                  };
              };
               //處理proxy-target-calss(true表示強制使用CGLIB動態代理)和expos-proxy屬性
               2.useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement());
               //注冊組件並通知。
          3.registerComponentIfNecessary(beanDefinition, parserContext);
          };
      }
  });
}

1.6.2 創建AOP代理

AnnotationAwareAspectJAutoProxyCreator繼承自AbstracAutoProxyCreator,有方法postProcessorAfterInitializatioin()

postProcessorAfterInitializatioin(){
   //封裝指定bean
   wrapIfNecessary(bean, beanName, cacheKey){
       1.各種直接返回場景,已處理、無需增強..
       2.獲取增強
         Object[] specificInterceptors = getAdviceAndAdvisorsForBean(bean.class, beanName, null){
          findEligibleAdvisors(beanClss, beanName){
              2.1 findCandidateAdvisors(){};
                   2.2 findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
                   return eligibleAdisors;
          };
        };
       3.如果有增強,則針對增強創建代理
      createProxy(bean,getClass(),beanName, specificInterceptors, new SingletoTargetSource(bean));
  };
}
2.
2.1 提取advisors
findCandidateAdvisors(){
   //將通過配置文件配置的AOP加載進來
   List<Advisor> advisors = super.findandidateAdvisors();
   2.1.1 advisors.addAll(this.aspectJAvdivsorsBuilder.buildAspectJAdvosprs());
   return advisors;
};

2.1.1
buildAspectJAdvispos(){
1.通過BeanFactoryUtils獲取所有beanNames,
   2.遍歷beanNames,進而獲取beanType
   3.如果beanType上有Aspect注解
       解析注解中的增強方法
   advisorFactory.getAdvisors(factory){
       
  };
   4.advisors.addAll();//記錄在緩存中並返回advisors
}
2.1.1.3
getAdvisors(factory){
   //普通增強器的獲取,包括切點注解的獲取和根據注解信息生成增強
   1.getAdvisor(...){
       //獲取切點注解
       getPointcut(...){
           //獲取方法上的注解
           aspectJAnnotation=findAspectJAnnotationOnMethod(...){
               1.設置注解敏感類
               2.遍歷敏感類與傳入的方法上的標注匹配,來確定是哪個注解
                   findAnnotation(method, class){}
          };
           //創建用於封裝獲取的信息的AspectJExpressionPointcut實例
           ajexp=new AspectJExpressionPointcut(...);
           //提取得到的注解中的表達式
           ajexp.setExpression(aspectJannotation.getPointcutExpression());
           return ajexp;
      };
       //根據獲取的切點信息生成增強器
       return new InstantiationModelAwarePointcutAdvisorImpl(...){
           1.簡單地將獲取的信息封裝在InstantiationModelAwarePointcutAdvisorImpl實例中
      2.
           //初始化對應的增強器
           instantiateAvice(){
               return ...getAdvice(...){
                   1.一些判斷邏輯
                   //根據不同的注解類型封裝不同的增強器
                   2.switch(aspectJAnnotation.getAnnotationType()){
                           case AtBefore....                                case AtAfter...                                case AtAfterReturning                               ....                   }               }           };       };   }    2.加入同步實例化增強器        //用於引介增強的注解    3.獲取DeclareParents        //與普通getAdvisors相像        getDelaredParentsAdvisor()};  ​2.2 找到滿足我們配置的通配符的增強器findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName){   遍歷candidateAdvisors   1.先處理引介增強 canApply{}    2.處理普通bean的增強 canApply{}};​3.createProxy(){    proxyFactory=new ProxyFactory();    1.//獲取當前類中相關屬性    proxyFactory.copyFrom(this);    2.//添加代理接口    proxyFactory.addInterface(targetInterFace of targetInterfaces);    3.//將攔截器(各種攔截器,增強器,增強方法)統一封裝為Advisor,並加入ProxyFactory中。    advisors = buildAdvisors(beanName, specificInterceptors){        1.處理commonIntercepotors和specficInterceptor,加入allInterceptors中,            //將攔截器(各種攔截器,增強器,增強方法)統一封裝為Advisor        2.advisros[i]=this.advisorAdapterRegistry.wrap(allInterceptors.get(i)){            根據傳入參數類型是                a.Advisor (直接返回)                b.Advice--1.MethodInterceptor...2.AdvisorAdapter DefaultPointcutAdvisor                c.其他類型拋出異常       };           };    //加入ProxyFactory中    proxyFactory.addAdvisor(advisor of advisors);    4.//設置要代理的類    proxyFactory.setTargetSource(targetSource);    5.//定制代理的一些屬性    customizeProxyFactory(proxyFactory);    6.//獲取代理並返回 AopProxy    return ProxyFactory.getProxy(this.proxyClassLoader){        //創建代理        1.return createAopProxy().getProxy(classLoader); {           };       };};​3.6.1.1createAopProxy(){      getAopProxyFactory().createAopProxy(this){      if(根據條件,選取代理方法 1.JDK動態代理,2.CGLIB)          new JdkDynamicAopProxy(config);          new CglibProxyFactory.createCglibProxy(config);}​

1.6.3 JDK動態代理和Cglib代理

1.JDK動態代理和Cglib的區別

​ JDK動態代理針對接口,無法針對類。目標類實現了接口,默認采用該方式。沒有實現必須CGLIB; CGLIB是針對類,生成子類,覆蓋方法,所以原類中的方法不能是final

2.JdkDynamicAopProxy

示例

public interface UserService{
   public abstract void add();
}

public class UserServiceImpl implements UserService{
   public void add(){
       System.out.println("-------------add-----------");
  }
}

//創建自定義的InvocationHandler,用於對接口的方法增強
//必須重寫的三個函數
public class MyInvocationHandler implements InvocatinHandler{
   private Object target;
   
   1.//將被代理對象傳入
   public MyInvocationHandler(Object target){
       super();
       this.target = target;
  }
 
   2.獲取代理對象
   public Object getProxy(){
       return Proxy.newProxyInstance(classLoader, target.getClass().getInterfaces(),this);
  }
   
   3.執行目標對象方法
   public Object invoke(Object proxy, Method method, Object[] args){
               System.out.println("-------------add-----------");
      Object result = method.invoke(target, args);
      System.out.println("-------------add-----------");
return result;
  }
}

3.jdk動態代理必須實現的三個接口

//必須重寫的三個函數
1.//將被代理對象傳入
   public MyInvocationHandler(Object target)
2.獲取代理對象
   public Object getProxy(){
3.執行目標對象方法
   public Object invoke(Object proxy, Method method, Object[] args){

4.Spring AOP JdkDynamicAopProxy也實現了InvocationHandler接口

public object invoke(Object proxy, Method method, Object[] args){
   1.....很多邏輯
   2.獲取當前方法的攔截器鏈 //並封裝再ReflectiveMethodInvocation中
   3.proceed() //執行攔截器鏈
}

5.CGLIB動態代理

委托給Cglib2AopProxy完成

getProxy(){
   1.創建enhancer
Enhancer enhancer = new createEnhancer();
   2.設置父類
   enhancer.setSuperclass(proxySuperClass);
   3.設置攔截器
   Callback[] callbacks = getCallbacks();
   enhancer.setCallbacks();
   4.生成代理類,以及創建代理
   proxy=enhancer.create();
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM