Spring-IOC源码解读2-容器的初始化过程
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-容器的初始化过程的更多相关文章
- Spring Ioc源码分析系列--容器实例化Bean的四种方法
Spring Ioc源码分析系列--实例化Bean的几种方法 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到bean真正通过那些方式实例化出来的时候,并没有继续分 ...
- Spring IoC源码解读——谈谈bean的几种状态
阅读Spring IoC部分源码有一段时间了,经过不断的单步调试和参阅资料,对Spring容器中bean管理有了一定的了解.这里从bean的几个状态的角度出发,研究下IoC容器. 一.原材料 Xml中 ...
- 精尽Spring MVC源码分析 - WebApplicationContext 容器的初始化
该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...
- Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析
Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...
- Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理
Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...
- Spring IOC 源码分析
Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...
- spring IoC源码分析 (3)Resource解析
引自 spring IoC源码分析 (3)Resource解析 定义好了Resource之后,看到XmlFactoryBean的构造函数 public XmlBeanFactory(Resource ...
- Spring IoC源码解析之invokeBeanFactoryPostProcessors
一.Bean工厂的后置处理器 Bean工厂的后置处理器:BeanFactoryPostProcessor(触发时机:bean定义注册之后bean实例化之前)和BeanDefinitionRegistr ...
- Spring IoC源码解析之getBean
一.实例化所有的非懒加载的单实例Bean 从org.springframework.context.support.AbstractApplicationContext#refresh方法开发,进入到 ...
随机推荐
- HDU 4044 GeoDefense (树形DP,混合经典)
题意: 给一棵n个节点的树,点1为敌方基地,叶子结点都为我方阵地.我们可以在每个结点安放炸弹,每点至多放一个,每个结点有ki种炸弹可选,且每种炸弹有一个花费和一个攻击力(1点攻击力使敌人掉1点hp). ...
- ArcGis server连接oracle
ArcGIG server连接Oracle 目录--gis服务器--添加arcgis server 下一步: 身份验证为在arcgis server manager 中的管理员登录密码和账户 对于服务 ...
- Jordan 标准型定理
将学习到什么 就算两个矩阵有相同的特征多项式,它们也有可能不相似,那么如何判断两个矩阵是相似的?答案是它们有一样的 Jordan 标准型. Jordan 标准型定理 这节目的:证明每个复矩阵都与一 ...
- 验证IP端与数据库Ip端是否重复!!!
select COUNT(id) from house_info_config hic where (hic.ip_start <![CDATA[<=]]> #{ipend} AND ...
- LeetCode || 双指针 / 单调栈
11. Container With Most Water 题意:取两根求最大体积 思路:使用两个指针分别指向头和尾,然后考虑左右两根: 对于小的那根,如果选择了它,那么能够产生的最大体积一定是当前的 ...
- var、let、const声明变量的区别
let和var声明变量的区别:1.let所声明的变量只在let命令所在的代码块内有效.(块级作用域) for(let i=0;i<10;i++){ // ... } console.log(i) ...
- SpringMVC+Spring+Mybatis整合程序之整合
因为每个人思路不一样,所以我在这边先分享自己的思路对于mybatis开发持久层(DAO:DataBase Access Object 持久层访问对象)有两种.第一种:传统的开发持久层方式即需要程序员开 ...
- 简单css动画 fadeIn fadeOut flash
考虑兼容性采用 -webkit- -o- -mos- -ms- @keyframes fadeIn{ 0%{ opacity: 0; display: block; } 100%{ opacity: ...
- UVa-101-木块问题
这题用vector比较好写,我们设置对应的几个函数,然后进行相应的操作来简化代码,这样才不易出错. 对于输入和操作来说我们经分析之后,可以看到最后一个操作时最原始的操作也就是不需要还原任意一个堆任意高 ...
- PAT Basic 1024
1024 科学计数法 科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式[+-][1-9]"."[0-9]+E[+-][0-9]+,即数字的整数部分只有1 ...