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