Spring 的核心就是 Bean,圍繞這 Bean 這個概念衍生出來 IOC(控制反轉),AOP(面向切面編程),該系列文章主要分析 IOC 源碼;php
IOC(控制反轉):意思就是將咱們日常編程中人爲建立對象和管理對象的這一系列複雜關係,交給 Spring 容器去作html
@Test
public void t5() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring_1.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.queryUser("long");
}
複製代碼
<?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 id="userService" class="com.example.ana.service.impl.UserServiceImpl" />
</beans>
複製代碼
根據以前保存的 configLocations 經過 ResourcePatternResolver(ResourceLoader 的子類) 進行解析返回 Resource[],覺得這裏咱們只有一個配置文件 spring_1.xml 因此返回數組只有一個值,Resource 表明一個資源,它描述了一個文件的相關信息 java
根據 Resource 獲取其 InputStream,其實就是 resource.getFile().getInputstream(),而後根據 InputStream 建立 InputSourcenode
而後調用 DefaultDocumentLoader 的 loadDocument(InputSource inputSource, EntityResolver entityResolver, ...) 方法spring
建立 DocumentBuilder編程
調用 parse(InputSource is)數組
最終調用 DomParser 的 parse(InputSource inputSource) 方法,將其解析爲 Documentapp
其實總結下來就一句話,根據 configLocations 對應的文件解析爲 Resource,而後經過 Resource 獲取到文件輸入流,最後經過 DomParser 將輸入流進行解析爲 Document測試
Document 是文檔的根節點,他的實現類,包含了 xml 或者 html 等文檔各個節點和命名空間的數據,好比說它其中的 Element 的 node 屬性就能包含 <bean id="xxx" class="xxx" />
這樣一個節點數據,可以獲取到它的 id、class 等,經過這個 Document 的信息就能比較方便的建立 BeanDefinition 了ui
http://www.springframework.org/schema/beans
這樣的命名空間,那麼就 BeanDefinitionParserDelegate 這個委派器解析 Element 元素將其解析後返回 BeanDefinitionHolder,解析流程不復雜大致就是經過 Element 獲取 bean 元素的 id,class,別名等信息來建立 BeanDefinitionHolder,new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray)
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
// 主要邏輯
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
this.beanDefinitionMap.put(beanName, beanDefinition);
}
複製代碼
spring 首先將配置文件解析爲 Resource,而後根據 Resouce 獲取其輸入流信息解析生成 Document 經過該 Document 獲取到的 Element 包含了定義的全部節點信息,而後經過 Element 獲取全部的 Bean 結點遍歷依次解析,解析就是經過這些結點獲取 bean 定義的 id、class、alias 等信息,根據這些信息來建立 BeanDefinition,最後將 BeanDefinition 放入 DefaultListableBeanFactory 的 BeanDefinitionMap 中同時保存一份 beanDefinitionNames