spring ioc 源码解析
Spring IOC的初始化流程
1、项目从 ApplicationContext app = new ClassPathXmlApplicationContext(“applicationContext.xml”);
2、找到工厂实现类【ClassPathXmlApplicationContext】中对应的构造方法,执行ioc容器初始化:
如下:
*使用给定的父类创建一个新的ClassPathXmlApplicationContext,
从给定的XML文件中加载定义。
* @param configLocations资源位置数组
是否自动刷新上下文,
加载所有bean定义并创建所有的单例。
*或者,在进一步配置上下文之后手动调用refresh。
* @param父上下文
如果上下文创建失败,@抛出BeansException
* @see # refresh ()
3、找到工厂抽象父类【AbstractApplicationContext】中的【refresh】方法:
3.1.该方法实现解析xml配置文件内容,封装成BeanDefinition对象,注册到BeanFactory中
3.2.该方法实现一些基础组件的注册:bean后置处理器组件、监听器组件、国际化资源组件
3.3.该方法实现bean对象的真正实例化。细节:初始化全部【singleton】单例对象,标记为【lazy-init】延迟加载的对象除外
流程小结:
1、在应用程序中初始化ioc容器的入口是 ClassPathXmlApplicationContext工厂实现类
2、在ClassPathXmlApplicationContext的构造方法中调用了refresh方法
2.1.refresh不仅仅是初始化ioc容器,如果已经有ioc容器了就更新容器
2.2.spring框架在处理过程中会考虑先释放已经存在的ioc容器。再重新创建一个ioc容器
3、spring框架允许在一个应用中有多个ioc容器,他们之间是父子关系。ssm框架就有两个ioc容器:
3.1通过ContextLoaderListener监听器,加载spring配置文件,创建的父容器
3.2通过DispatcherServlet前端控制器加载springmvc主配置文件创建的子容器
4、spring框架在创建ioc容器时,主体流程:
4.1设置容器的初始化状态,如:容器的启动时间,容器的**状态
4.2解析bean.xml配置文件,将配置文件中的信息解析封装程BeanDefinition对象
4.3将BeanDefinition对象注册到BeanFactory容器中。此时还没有真正创建bean对象,只是解析封装xml配置文件的内容
4.4设置一些公共资源。如:bean的后置处理器,类加载器,监听器,国际化资源等
4.5根据BeanDefinition对象真正创建bean对象, 此时创建的全是单例【singleton】,并且不是延迟加载【lazy-init】的对象
4.6最后一步广播事件,进行善后处理
[size=1em]CustomerController
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/** * 客户表现层 */ public class CustomerController { public static void main(String[] args) { // 1.加载spring 配置文件,初始化创建ioc容器 ApplicationContext context = new ClassPathXmlApplicationContext( "classpath:bean.xml" ); // 2.从ioc容器获取service CustomerService customerService = (CustomerService)context.getBean( "customerService" ); // 3.保存客户操作 customerService.saveCustomer(); } } |
[size=1em]ClassPathXmlApplicationContext
[size=1em]
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext { // 资源配置文件成员变量,是一个数组,支持多个spring的配置文件 @Nullable private Resource[] configResources; // 默认构造方法 public ClassPathXmlApplicationContext() { } // 如果已经存在一个ioc容器,可以在构造的时候设置【父】容器 public ClassPathXmlApplicationContext(ApplicationContext parent) { super (parent); } // 【重点跟踪】根据xxx.xml配置文件,创建ioc容器 public ClassPathXmlApplicationContext(String configLocation) throws BeansException { this ( new String[]{configLocation}, true , (ApplicationContext) null ); } .......................................... /** *【重点跟踪】方法说明: * 根据xml文件的定义,以及父容器,创建一个新的ClassPathXmlApplicationContext * *参数说明: * configLocations:xml配置文件数组 * refresh:是否要重新创建ioc容器。加载全部bean的定义和创建所有的单例对象 * parent:父容器 */ public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super (parent); // 设置父容器 // 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割) this .setConfigLocations(configLocations); if (refresh) { this .refresh(); // 【核心方法】:该方法表示初始化(或者重建)ioc容器。即可以把原来的ApplicationContext销毁,重新执行初始化创建 } } .......................................... } |
[size=1em]
[size=1em]AbstractApplicationContext
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext { .......................................... / * * * 【重点跟踪】方法说明: * 【核心方法】:该方法表示初始化(或者重建)ioc容器。即可以把原来的ApplicationContext销毁,重新执行初始化创建 * / public void refresh ( ) throws BeansException , IllegalStateException { / / 创建ioc容器,同步加锁,保障线程安全 synchronized ( this.startupShutdownMonitor ) { / / 准备工作:记录容器启动的时间,和状态标记 prepareRefresh ( ) ; / / 关键步骤: / / 1. 根据配置文件中配置内容,解析成一个个Bean实例(BeanDefinition) / / 2. 将一个个Bean实例,注册到BeanFactory中 / / 3. 细节:这里的Bean实例仅仅是描述Bean的相关信息,此时还没有真正创建对应的bean对象 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory ( ) ; / / 设置BeanFactory: / / 1. 设置类加载器 / / 2. 设置BeanPostProcessor(bean后置处理器) / / 3. 注册特殊的bean(框架内部使用的bean) prepareBeanFactory ( beanFactory ) ; try { / / 设置BeanFactoryPostProcessor postProcessBeanFactory ( beanFactory ) ; / / 调用BeanFactoryPostProcessor各个实现类的 postProcessBeanFactory ( factory ) 方法 / / 与上一步合起来,可以理解为是给Bean提供的一种扩展机制。比如可以让我们的
|