Spring IOC之ClassPathXmlApplicationContext启动深入源码分析(一)


AnnotationConfigApplicationContext是Spring用来加载注解配置的ApplicationContext,它是如何加载所有的bean,与ClassPathXmlApplicationContext有什么区别,让我们接下来揭开它的神秘面纱。

一、版本:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.12.RELEASE</version>
</dependency>

二、类图

类图

三、时序图

IOC

四、源码剖析

4.1 初始化IOC容器

目标类:ClassPathXmlApplicationContext

// new ClassPathXmlApplicationContext("applocationContext.xml")
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {

    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

4.2 设置配置文件路径

目标类:AbstractRefreshableConfigApplicationContext

public void setConfigLocations(String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

4.2 刷新IOC容器

目标类:AbstractApplicationContext

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 准备此上下文以进行刷新,设置其启动日期和活动标志,以及执行属性源的任何初始化。
        prepareRefresh();

        // 告知子类刷新Bean工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 注册IOC的后置处理器和类加载器
        prepareBeanFactory(beanFactory);

        try {
            // 允许调用容器子类Bean工厂进行后处理, 如BeanPostProcessor
            postProcessBeanFactory(beanFactory);
            
            // 调用容器中注册的Bean工厂处理器
            invokeBeanFactoryPostProcessors(beanFactory);
            
            // 注册拦截Bean创建的处理器
            registerBeanPostProcessors(beanFactory);

            // 初始化容器消息源
            initMessageSource();
            
            // 为容器初始化事件多播器。
            initApplicationEventMulticaster();

            // 在特定容器子类中初始化其他特殊Bean
            onRefresh();

            // 检查Bean监听者并注册
            registerListeners();
            
            // 实例化所有剩余的(非@Lazy)单例。
            finishBeanFactoryInitialization(beanFactory);
            
           // 最后一步:广播完成事件
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // 销毁已创建的单例, 避免资源浪费。
            destroyBeans();
            
            // 重置标志位:active
            cancelRefresh(ex);

            throw ex;
        }

        finally {
            // 重置Spring缓存,如:不再需要单例Bean的元数据信息...
            resetCommonCaches();
        }
    }
}

4.3 刷新Bean工厂

目标类:AbstractApplicationContext

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
	// 刷新Bean工厂
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

4.4 刷新BeanFactory

目标类:AbstractRefreshableConfigApplicationContext

// 覆盖AbstractApplicationContext的抽象方法
@Override
protected final void refreshBeanFactory() throws BeansException {
	// 销毁已存在的beanFactory
	if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
    	// 创建工厂
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        // 加载xml定义的beanDefinition信息
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " 
              + getDisplayName(), ex);
    }
}

4.5 创建工厂

目标类:AbstractRefreshableConfigApplicationContext

protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

4.6 加载Xml中定义的Bean信息

// 覆盖AbstractRefreshableConfigApplicationContext类的抽象方法
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 创建XmlBeanDefinitionReader, 用于读取XML中定义的Bean配置
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 配置beanDefinitionReader的加载资源环境
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // 初始化beanDefinitionReader, 并且加载BeanDefinition信息
    initBeanDefinitionReader(beanDefinitionReader);
    loadBeanDefinitions(beanDefinitionReader);
}

五、简化IOC启动源码

package com.ioteye.spring.annotation.xml;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;

import java.util.Date;

@Slf4j
public class XmlIOCStartup {
    public static void main(String[] args) {
    	// classpath资源加载器
        ClassPathResource resource = new ClassPathResource("spring.xml");
		// 默认的BeanFactory
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        
		// 读取xml BeanDefinition的阅读器
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        
		// 加载配置文件的定义
        reader.loadBeanDefinitions(resource);
        
		// 读取容器Bean
        Date date = factory.getBean(Date.class);
        log.info("bean = {}", date);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值