Spring源碼解析容器初始化構(gòu)造方法_第1頁
Spring源碼解析容器初始化構(gòu)造方法_第2頁
Spring源碼解析容器初始化構(gòu)造方法_第3頁
Spring源碼解析容器初始化構(gòu)造方法_第4頁
Spring源碼解析容器初始化構(gòu)造方法_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Spring源碼解析容器初始化構(gòu)造方法目錄前言構(gòu)造方法

前言

Spring框架被廣泛應(yīng)用于我們的日常工作中,但是很長時間以來我都是只會使用,不懂它的作用原理。通過最近一段時間的閱讀源碼,個人發(fā)現(xiàn)通過閱讀源碼,能夠幫助我們了解Spring的設(shè)計理念,并且對Java編程中的一些設(shè)計模式更加熟悉,所以記錄一下自己對Spring源碼的理解。

在開始進行源碼學(xué)習(xí)前,首先再回顧一下三種Spring編程風(fēng)格:

基于Schema,即通過xml標(biāo)簽的配置方式基于Annotation的注解技術(shù),使用@Component等注解配置bean基于JavaConfig,簡單來說就是使用@Configuration和@Bean進行配置

基于注解的方式需要通過xml或javaconfig來開啟。

在使用xml時,需要手動開啟對注解的支持:

context:annotation-config/

當(dāng)然,如果在xml中配置了掃描包,現(xiàn)在也可以光添加下面這一行,這行代碼中已經(jīng)包含了注解的開啟功能。

context:component-sacnbase-package="com"/

如果你使用的是下面AnnotationConfigApplicationContext這種方式,那么就不需要添加任何操作了,其中已經(jīng)包含了對注解的支持。

AnnotationConfigApplicationContextctx

=newAnnotationConfigApplicationContext(SpringConfig.class);

在實際使用過程中,三種方式是可以混合使用的,不存在沖突。按照下面這種方式作為AnnotationConfigApplicationContext傳入的配置文件,即可實現(xiàn)三種風(fēng)格的統(tǒng)一使用:

@Configuration

@ComponentScan("com")

@ImportResource("classpath:spring.xml")

publicclassSpringConfig{

}

之前也有小伙伴對我說,在開始學(xué)習(xí)Spring的時候,差點因為配置繁雜的xml被勸退,我也翻閱了一下網(wǎng)上spring入門的技術(shù)文章,確實很多還是停留在使用xml的方式上。但是其實如果你翻閱一下spring5的官方文檔,可以看出官方是推薦我們使用注解的方式的。

尤其是現(xiàn)在的SpringBoot更多的是基于注解,省略了很多配置的過程,對新手更加友好,降低了勸退率,所以本文將基于注解的方式進行源碼解析,另外再說明一下本文基于spring-framework-5.0.x源碼。

使用注解的方式初始化一個Spring環(huán)境,只需要下面一行代碼:

AnnotationConfigApplicationContextcontext

=newAnnotationConfigApplicationContext(SpringConfig.class);

如果看一下它的構(gòu)造方法,那么可以將它做的工作拆分為三步,為了便于理解可以寫成下面的形式,并分為三大模塊分別進行說明。

構(gòu)造方法

首先看一下AnnotationConfigApplicationContext的繼承關(guān)系:

AnnotationConfigApplicationContext繼承了GenericApplicationContext,那么我們先看GenericApplicationContext的構(gòu)造方法:

publicGenericApplicationContext(){

this.beanFactory=newDefaultListableBeanFactory();

}

在這里初始化了一個beanFactory的實現(xiàn)類DefaultListableBeanFactory,這就是我們常提到的spring中重要的bean工廠,這里面存放了很多非常重要的數(shù)據(jù)結(jié)構(gòu)。這里先列出比較重要的beanDefinitionMap,會在后面頻繁使用:

privatefinalMapString,BeanDefinitionbeanDefinitionMap=newConcurrentHashMap(256);

privatevolatileListStringbeanDefinitionNames=newArrayList(256);

在上面的這個beanDefinitionMap中就維護了beanName及BeanDefinition的對應(yīng)關(guān)系,beanDefinitionNames則是一個存放beanName的List。

從AnnotationConfigApplicationContext的構(gòu)造方法開始分析:

publicAnnotationConfigApplicationContext(){

this.reader=newAnnotatedBeanDefinitionReader(this);

this.scanner=newClassPathBeanDefinitionScanner(this);

}

首先實例化了一個AnnotatedBeanDefinitionReader對象,看一下AnnotatedBeanDefinitionReader的構(gòu)造函數(shù):

publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistryregistry){

this(registry,getOrCreateEnvironment(registry));

}

那么,為什么在這能夠?qū)nnotationConfigApplicationContext對象作為BeanDefinitionRegistry傳入呢?

回頭看一下繼承關(guān)系那張圖,AnnotationConfigApplicationContext繼承了BeanDefinitionRegistry,并且最終實現(xiàn)了接口BeanFactory,BeanFactory可以說是Spring中的頂層類,它是一個工廠,能夠產(chǎn)生bean對象,提供了一個非常重要的方法getBean,會在后面講到。

到這,我們可以得出一個結(jié)論:

BeanDefinitionRegistry可以等同于AnnotationConfigApplicationContext,看做spring的上下文環(huán)境。

AnnotatedBeanDefinitionReader在實例化時,會調(diào)用registerAnnotationConfigProcessors方法。先看前半段代碼:

publicstaticSetBeanDefinitionHolderregisterAnnotationConfigProcessors(

BeanDefinitionRegistryregistry,@NullableObjectsource){

DefaultListableBeanFactorybeanFactory=unwrapDefaultListableBeanFactory(registry);

if(beanFactory!=null){

if(!(beanFactory.getDependencyComparator()instanceofAnnotationAwareOrderComparator)){

beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);

if(!(beanFactory.getAutowireCandidateResolver()instanceofContextAnnotationAutowireCandidateResolver)){

beanFactory.setAutowireCandidateResolver(newContextAnnotationAutowireCandidateResolver());

}

在這里先獲取在父類構(gòu)造函數(shù)中實例好的beanFactory,并為它填充一些屬性:

AnnotationAwareOrderComparator:主要用于排序,解析@order和@Priority注解ContextAnnotationAutowireCandidateResolver:提供處理延遲加載的功能

再看后半段代碼,下面生成了6個重要類的BeanDefinitionHolder,并存放到一個Set中:

SetBeanDefinitionHolderbeanDefs=newLinkedHashSet(8);

if(!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition(ConfigurationClassPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

if(!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

if(!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));

//CheckforJSR-250support,andifpresentaddtheCommonAnnotationBeanPostProcessor.

if(jsr250Present!registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition(CommonAnnotationBeanPostProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));

//CheckforJPAsupport,andifpresentaddthePersistenceAnnotationBeanPostProcessor.

if(jpaPresent!registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition();

try{

def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,

AnnotationConfigUtils.class.getClassLoader()));

catch(ClassNotFoundExceptionex){

thrownewIllegalStateException(

"Cannotloadoptionalframeworkclass:"+PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,ex);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));

if(!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition(EventListenerMethodProcessor.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,EVENT_LISTENER_PROCESSOR_BEAN_NAME));

if(!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)){

RootBeanDefinitiondef=newRootBeanDefinition(DefaultEventListenerFactory.class);

def.setSource(source);

beanDefs.add(registerPostProcessor(registry,def,EVENT_LISTENER_FACTORY_BEAN_NAME));

returnbeanDefs;

}

這里是使用RootBeanDefinition來將普通類轉(zhuǎn)換為BeanDefinition,并進一步封裝成BeanDefinitionHolder。封裝成BeanDefinitionHolder的操作在registerPostProcessor方法中:

privatestaticBeanDefinitionHolderregisterPostProcessor(

BeanDefinitionRegistryregistry,RootBeanDefinitiondefinition,StringbeanName){

definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

registry.registerBeanDefinition(beanName,definition);

returnnewBeanDefinitionHolder(definition,beanName);

}

通過registerBeanDefinition方法將BeanDefinition注冊到spring環(huán)境

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論