1. IOC容器的初始化过程:IOC容器的初始化由refresh()方法启动,这个启动包括:BeanDifinition的Resource定位,加载和注册三个过程。初始化的过程不包含Bean依赖注入的实现。

  • 第一个过程是Resource的定位过程。这个Resource的定位指的是BeanDefinition的资源定位,它由ResourceLoader通过统一的Resource接口完成。
  • 第二个过程是BeanDefinition的载入,这个过程是把用户定义好的Bean表示为容器的内部数据结构(即BeanDefinition)
  • 第三个过程是向IOC容器注册这些BeanDefinition的过程。

2. 下面我们以ClassPathXmlApplicationContext 为例分析这个ApplicationContext的实现,使用的spring版本是3.0.2版本。首先看下我们测试的代码和配置文件:

  • 2.1:javaBean的定义
public class Person {
private String name;
private int age;
private int sex;
private Dog dog;
private List<Address> addressList;
      
} public class Dog {
private String dogName;
} public class Address {
private String type;
private String city;
}
  • 2. 2beans.xml文件定义:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- person对象 -->
<bean id="person" class="com.pepper.spring.model.Person" >
<property name="name" value="pepper" />
<property name="age" value="24" />
<property name="sex" value="1" />
<property name="dog" ref="dog" />
<property name="addressList">
<list>
<ref bean="home"/>
<ref bean="work"/>
</list>
</property>
</bean> <!-- person对象的Dog属性 -->
<bean id="dog" class="com.pepper.spring.model.Dog">
<property name="dogName" value="Edward" />
</bean> <!-- person对象AddressList属性的两个值 -->
<bean id="home" class="com.pepper.spring.model.Address">
<property name="type" value="home" />
<property name="city" value="SX" />
</bean>
<bean id="work" class="com.pepper.spring.model.Address">
<property name="type" value="work" />
<property name="city" value="SZ" />
</bean>
</beans>
  • 2.3. 容器启动类:
public class TestSpring {

	public static final String BEAN_CONFIG_FILE = "E:/workspace_selflearn/read-spring/src/spring-beans.xml";
public static final String BEAN_CONFIG_CLASS = "spring-beans.xml"; public static void main(String[] args) {
testApplicationContext();
}
//使用XmlBeanFactory
public static void testBeanFactory() {
Resource res = new ClassPathResource(BEAN_CONFIG_CLASS);
BeanFactory fac = new XmlBeanFactory(res);
Person p = fac.getBean("person", Person.class);
System.out.println(p);
} //使用ApplicationContext
public static void testApplicationContext() {
ApplicationContext ac = null;
// ac = new FileSystemXmlApplicationContext(BEAN_CONFIG_FILE);
ac = new ClassPathXmlApplicationContext(BEAN_CONFIG_CLASS);
Person p = ac.getBean("person", Person.class);
System.out.println(p);
}
}

3. 我们先看下ClassPathXmlApplicationContext类的定义:

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {

    private Resource[] configResources;

    public ClassPathXmlApplicationContext() {
} public ClassPathXmlApplicationContext(ApplicationContext parent) {
super(parent);
}
// configLocation对象表示BeanDefinition所在的文件路径
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
// Spring支持传入多个BeanDefinition配置文件
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
// 此构造方法除了包含配置文件路径,还允许指定想要使用的父类IOC容器
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
} public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
this(configLocations, refresh, null);
}
//对象的初始化过程中,调用refresh()方法启动BeanDefinition的载入过程
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
} public ClassPathXmlApplicationContext(String[] paths, Class clazz) throws BeansException {
this(paths, clazz, null);
} public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent) throws BeansException { super(parent);
Assert.notNull(paths, "Path array must not be null");
Assert.notNull(clazz, "Class argument must not be null");
this.configResources = new Resource[paths.length];
for (int i = 0; i < paths.length; i++) {
this.configResources[i] = new ClassPathResource(paths[i], clazz);
}
refresh();
}
//获取资源配置文件
@Override
protected Resource[] getConfigResources() {
return this.configResources;
} } 

容器启动的时候会调用ClassPathXmlApplicationContext的构造方法,在这个构造方法中会调用refresh()方法,这个方法十分重要,这是我们分析容器初始化过程中至关重要的一个接口,我们后面分析的Bean的载入,解析,注册都是以这个方法作为入口开始的。

public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.准备上下文
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.通知子类刷新内部的bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.准备beanfactory来使用这个上下文.做一些准备工作,例如classloader,beanfactoryPostProcessor等
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.在子类上下文中允许beanfactory进行后置处理
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.调用工厂处理器作为bean注册到上下文中
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.开始注册BeanPostProcessor来拦截bean的创建过程
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.为上下文初始化消息源
initMessageSource(); // Initialize event multicaster for this context.为上下文初始化事件广播
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.在具体的子类上下文中初始化特殊的bean
onRefresh(); // Check for listener beans and register them.检查监听器bean并注册
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.实例化所有的剩余的singleton的bean
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.最后一步,发布应用
finishRefresh();
} catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
}
}
}

  

Spring-IOC源码解读2-容器的初始化过程的更多相关文章

  1. Spring Ioc源码分析系列--容器实例化Bean的四种方法

    Spring Ioc源码分析系列--实例化Bean的几种方法 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到bean真正通过那些方式实例化出来的时候,并没有继续分 ...

  2. Spring IoC源码解读——谈谈bean的几种状态

    阅读Spring IoC部分源码有一段时间了,经过不断的单步调试和参阅资料,对Spring容器中bean管理有了一定的了解.这里从bean的几个状态的角度出发,研究下IoC容器. 一.原材料 Xml中 ...

  3. 精尽Spring MVC源码分析 - WebApplicationContext 容器的初始化

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  4. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  5. Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理

    Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...

  6. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  7. spring IoC源码分析 (3)Resource解析

    引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource  ...

  8. Spring IoC源码解析之invokeBeanFactoryPostProcessors

    一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...

  9. Spring IoC源码解析之getBean

    一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...

随机推荐

  1. 虚拟机ubuntu16.0 安装 mysql 主机配置访问

    在bantu服务器中安装如下命令 sudo apt-get install mysql-server    sudo apt-get install mysql-client安装成功之后 进入配置文件 ...

  2. springmvc+maven搭建web项目

    1.创建一个maven project 为spring1 2.进行项目的配置:默认的java 1.5 在properties中选择project facts项目进行配置,反选web之后修改java环境 ...

  3. 找出指定文件夹中的所有以txt结尾的文件,包括所有嵌套的子文件夹

    # coding:utf-8 import os, re for i in os.walk('d:'+os.sep):     for txt in i[2]:         try:        ...

  4. jquery的同步和异步

    之前一直在写JQUERY代码的时候遇到AJAX加载数据都需要考虑代码运行顺序问题.最近的项目用了到AJAX同步.这个同步的意思是当JS代码加载到当前AJAX的时候会把页面里所有的代码停止加载,页面出去 ...

  5. Hibernate 中批量处理数据

    一.批量处理操作 批量处理数据是指在一个事务场景中处理大量数据.在应用程序中难以避免进行批量操作,Hibernate提供了以下方式进行批量处理数据: (1)使用HQL进行批量操作     数据库层面 ...

  6. shell脚本,通过传参求斐波那契数列如(0,1,1,2,3,5,8,13..........)

    [root@localhost wyb]# cat fibo.sh #!/bin/bash #斐波那契数列 ,,,,,,, > file >> file count=$ for i ...

  7. 【贪心】bzoj1045: [HAOI2008] 糖果传递

    很妙的贪心思考过程 Description 有n个小朋友坐成一圈,每人有ai个糖果.每人只能给左右两人传递糖果.每人每次传递一个糖果代价为1. Input 第一行一个正整数nn<=1'000'0 ...

  8. 初涉「带权并查集」&&bzoj3376: [Usaco2004 Open]Cube Stacking 方块游戏

    算是挺基础的东西 Description     约翰和贝茜在玩一个方块游戏.编号为1到n的n(1≤n≤30000)个方块正放在地上.每个构成一个立方柱.    游戏开始后,约翰会给贝茜发出P(1≤P ...

  9. [LUOGU] P2245 星际导航

    题目描述 sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为了方便起见,我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向图,顶点表示各个星系, ...

  10. leepcode作业解析 - 5-20

    22.缺失数字 给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数. 示例 1: 输入: [3,0,1] 输出: 2 示例 2: 输入: ...