成熟丰满熟妇高潮XXXXX,人妻无码AV中文系列久久兔费 ,国产精品一国产精品,国精品午夜福利视频不卡麻豆

您好,歡迎來到九壹網(wǎng)。
搜索
您的當(dāng)前位置:首頁Spring源碼筆記之SpringIOC--(1)從XML文件到Bean的描述對象BeanDefinition

Spring源碼筆記之SpringIOC--(1)從XML文件到Bean的描述對象BeanDefinition

來源:九壹網(wǎng)
從XML文件到Bean的描述對象BeanDefinition

最開始學(xué)習(xí)spring的入門實踐是,編寫一個xml文件,然后利用spring讀取xml文件中配置的bean。
編寫一個xml配置文件default.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean name="myBean" class="org.numb.springframework.ioc.bean.MyBean"/>
</beans>

編寫代碼加載這個bean,并獲取bean的實例

public void test() {
	 BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("default.xml"));
    MyBean myBean = (MyBean) beanFactory.getBean("myBean");
}

至此就實現(xiàn)了springIOC加載一個bean的功能。其實在Spring代碼中提供了現(xiàn)有的測試用例,可以從測試用例入手了解源碼。注意XmlBeanFactory自spring 3.x后逐步廢棄,使用XmlBeanDefinitionReader替代。查看其測試類XmlBeanDefinitionReaderTests

withClassPathResource()測試方法

class XmlBeanDefinitionReaderTests {
    
    private final SimpleBeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
    
	private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(registry);
    
    @Test
	void withClassPathResource() {
        // 讀取test.xml的資源文件
		Resource resource = new ClassPathResource("test.xml", getClass());
        // 加載資源
		reader.loadBeanDefinitions(resource);
        // 斷言檢查
        assertThat(registry.getBeanDefinition("rod").getBeanClassName()).isEqualTo(TestBean.class.getName());
	}
}

上述測試用例中,spring使用ClassPathResource讀取bean定義test.xml文件,然后使用XmlBeanDefinitionReader加載資源,加載過程中會解析test.xml,單步調(diào)試一下loadBeanDefinitions方法的調(diào)用過程

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    // 為了適配字符集與編碼,統(tǒng)一交由EncodedResource來讀取資源
    return loadBeanDefinitions(new EncodedResource(resource));
}

首先將Resource->EncodedResource來加載,EncodedResource內(nèi)部主要適配了編碼和字符集,這步不用太關(guān)心。后面使用EncodedResource加載,這里借助NamedThreadLocal獲取當(dāng)前待加載的資源currentResources,然后判斷資源是否能add到currentResources的set中,如果能add說明Resource未被加載,等加載完成后再remove,避免重復(fù)加載相同的Resource。

獲取待加載的資源currentResources
加入待加載資源集
注冊beans
加載完成移出待加載資源集
XmlBeanDefinitionReader
loadBeanDefinitions()
resourcesCurrentlyBeingLoaded.get()
currentResources.add()
doLoadBeanDefinitions()
currentResources.remove()

重點在于doLoadBeanDefinitions()方法

解析資源對象
注冊BeanDefinition
創(chuàng)建BeanDefinitionDocumentReader
創(chuàng)建XmlReaderContext
傳入Document
傳入XmlReaderContext
doLoadBeanDefinitions()
doLoadDocument()
registerBeanDefinitions()
createBeanDefinitionDocumentReader()
createReaderContext()
Document
BeanDefinitionDocumentReader
XmlReaderContext
registerBeanDefinitions()

BeanDefinitionDocumentReader接口根據(jù)document讀取Bean的定義,并注冊進XmlReaderContext中,XmlReaderContext內(nèi)包含了xml加載的ResourceXmlBeanDefinitionReader等必要對象的封裝。具體bean的加載實現(xiàn)在DefaultBeanDefinitionDocumentReader中的doRegisterBeanDefinitions()。此處doRegisterBeanDefinitions()會被遞歸調(diào)用,BeanDefinitionParserDelegate是類內(nèi)的對象,所以為了保證遞歸調(diào)用時類內(nèi)能夠使用正確的Delegate,此處createDelegate()會模擬堆棧調(diào)用過程,將parent delegate傳入生成當(dāng)前的delegate。

根據(jù)BeanDefinitionParserDelegate parent
創(chuàng)建當(dāng)前的Delegate
判斷是否是默認(rèn)xml命名空間
跳過不接受的profile定義的bean
預(yù)處理
解析bean定義,注冊入XmlReaderContext中
后處理
doRegisterBeanDefinitions()
createDelegate()
isDefaultNamespace()
preProcessXml()
parseBeanDefinitions()
postProcessXml()
BeanDefinitionParserDelegate
acceptsProfiles()

parseBeanDefinitions()方法是具體將xml定析的實現(xiàn)

處理XML的Element
解析import
解析alias
解析bean
解析beans
遞歸調(diào)用
解析bean的定義
命名空間處理器裝飾bean
注冊bean定義到XmlReaderContext.BeanDefinitionRegistry
發(fā)送注冊事件
parseBeanDefinitions()
parseDefaultElement()
importBeanDefinitionResource()
processAliasRegistration()
processBeanDefinition()
doRegisterBeanDefinitions()
delegate.parseBeanDefinitionElement()
decorateBeanDefinitionIfRequired()
BeanDefinitionReaderUtils.registerBeanDefinition()
getReaderContext().fireComponentRegistered()

到此為止,spring的XmlBeanDefinitionReader將xml文件使用Resource讀取,并解析為Bean的定義為BeanDefinition,然后注冊入XmlReaderContext.BeanDefinitionRegistry中,中間類的調(diào)用關(guān)系如下。

doLoadDocument()
傳入
createBeanDefinitionDocumentReader()
createReaderContext()
傳入
傳入
createDelegate()
生成
傳入
processBeanDefinition()
?interface?
Resource
ClassPathResource
基于類路徑的資源加載
EncodedResource
+Resource resource;
+String encoding;
+Charset charset;
Document
XML文件描述
XmlBeanDefinitionReader
+BeanDefinitionRegistry registry
+loadBeanDefinitions(resource : Resource) : int
BeanDefinitionRegistry
注冊BeanDefinition的接口
+registerBeanDefinition
SimpleBeanDefinitionRegistry
BeanDefinitionRegistry的簡單實現(xiàn)
BeanDefinitionDocumentReader
基于Document解析Bean定義
DefaultBeanDefinitionDocumentReader
+registerBeanDefinitions(Document, XmlReaderContext)
+doRegisterBeanDefinitions(Element)
XmlReaderContext
上線文封裝類
+XmlBeanDefinitionReader reader;
BeanDefinitionParserDelegate
Xml的Bean解析代理類
+parseBeanDefinitionElement(Element, BeanDefinitionHolder) : BeanDefinitionHolder
+decorateBeanDefinitionIfRequired(Element, BeanDefinitionHolder) : BeanDefinitionHolder
BeanDefinitionHolder
BeanDefinition的holder
BeanDefinitionReaderUtils
工具類
+createBeanDefinition() : AbstractBeanDefinition
+registerBeanDefinition(BeanDefinitionHolder, BeanDefinitionRegistry)

去除各個子類實現(xiàn)類,以及xxxUtil、xxxHolder、xxxConetxt等工具類,簡單羅列一下頂層接口的交互過程

傳入
解析bean定義
注冊bean
?interface?
BeanDefinitionRegistry
注冊bean定義BeanDefinition的接口
?interface?
BeanDefinitionReader
讀取bean定義BeanDefinition的接口
?interface?
Resource
spring中資源描述符接口,用于加載資源文件
?interface?
BeanDefinition
用戶描述Bean定義的接口

spring定義了幾個bean操作的頂層接口BeanDefinitionRegistryBeanDefinitionReader、BeanDefinitionReaderResource,上述過程完成了XML資源文件到Bean的描述對象BeanDefinition的注冊過程,但是實際使用IOC過程中,并不是直接使用BeanDefinition,而是直接獲取bean實例,可以查看測試用例XmlBeanDefinitionReaderTestsdoTestValidation()方法

private void doTestValidation(String resourceName) {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    Resource resource = new ClassPathResource(resourceName, getClass());
    new XmlBeanDefinitionReader(factory).loadBeanDefinitions(resource);
    assertThat((TestBean) factory.getBean("testBean")).isNotNull();
}

對比此處與上面的不同之處在于,此處XmlBeanDefinitionReader的入?yún)⒂?code>SimpleBeanDefinitionRegistry變?yōu)?code>DefaultListableBeanFactory。DefaultListableBeanFactory中提供方法factory.getBean("testBean")直接獲取名為testBean的bean對象,而不是獲取BeanDefinition。

因篇幅問題不能全部顯示,請點此查看更多更全內(nèi)容

Copyright ? 2019- 91gzw.com 版權(quán)所有 湘ICP備2023023988號-2

違法及侵權(quán)請聯(lián)系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市萬商天勤律師事務(wù)所王興未律師提供法律服務(wù)