这一章节先搭建一个项目来体验下Spring的初始化流程:
project.pngpom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sailfish</groupId>
<artifactId>learn-spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>learn-spring</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
UserService
public class UserService {
public void sayHello(){
System.out.println("hello springIoc!");
}
}
Client
public class Client {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-ioc.xml");
UserService userService = (UserService) context.getBean("userService");
userService.sayHello();
}
}
applicationContext-ioc.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 id="userService" class="com.sailfish.learnspring.ioc.UserService">
</bean>
</beans>
运行结果:
image.png其实主要分析的就只有一段代码:ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-ioc.xml");
但就是这一段代码,系统其实是做了很多事情的:
Debug开始:
image.png- 函数功能:从给定的XML(configLocations)中加载BeanDefinition
- refresh含义:是否刷新上下文
- 框一:ConfigurableApplicationContext接口的实现(ConfigurableApplicationContext接口先保留,之后分享)
- 实际设置AbstractRefreshableConfigApplicationContext类的configLocations属性
- 主要看如何初始化BeanFactory,也就是515行
- 在线程安全的情况下返回AbstractRefreshableApplicationContext类的BeanFactory,也就是refreshBeanFactory方法设置的BeanFactory
- 方法功能:执行该上下文底层的实际刷新bean工厂,关闭以前的bean工厂(如果有的话),在上下文生命周期的下一个阶段初始化一个新的bean工厂。
- 121-124行:判断是否存在beanFactory,如果存在那么就销毁BeanFactory,保证只有一个BeanFactory
- 126行创建了一个新的BeanFactory
- 128行:定制这个上下文所使用的内部bean工厂。
- 129行:通过XmlBeanDefinitionReader加载BeanDefinition
- 实际从指定的XML文件加载bean定义
- 方法功能:注册给定DOM文档中包含的bean定义。
- 上面出现了好几个loadBeanDefinitions方法,这是Spring对BeanDefinition做转换,最开始拿到的是File,要将其转为Document做解析
- 注册给定根<bean />元素中的每个bean定义
- 解析文档中根级别的元素:“import”,“alias”,“bean”
- 处理给定的bean元素,解析bean定义并将其注册到注册表
- 148行:获取beanName
- 149行:注册BeanDefinition,key为beanName,value为BeanDefinition
- 152-155:从BeanDefinition中获取Aliases,如果有,则注册别名
总结
本章是围绕一个简单的实例来进行,主要解析了refresh方法创建BeanFactory的过程,后面的一些讲解会配套的过一下相关的组件,本片文章主要借鉴Spring源码深度解析,CSDN上的博客和Spring文档及源码注释,代码已经上传到Github,可以从Github上下载源码,文章有很多不足,自己的深度不够,只能顺着流程捋一遍,不能完全理解Spring设计者的思想...
网友评论