共计 15146 个字符,预计需要花费 38 分钟才能阅读完成。
0. 简介
本文以 ClassPathXmlApplicationContext 源码学习 Spring 初始化流程,那么首先要了解它实现了哪些接口,可以直观地了解到它具备了哪些能力。

最重要的一点是它实现了 BeanFactory 接口,BeanFactory 其实就是常说的 ioc 容器,因为它实现了该接口,所以 ClassPathXmlApplicationContext 也是 ioc 容器。重点来了,ClassPathXmlApplicationContext 虽然实现了接口,但是它重写 BeanFactory 的方法都是委托给了成员变量 beanFactory 去实现。下面的代码都是其基类实现的。
// AbstractApplicationContext 实现
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
    assertBeanFactoryActive();
    return getBeanFactory().getBean(requiredType);
}
// AbstractRefreshableApplicationContext 实现
@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
    DefaultListableBeanFactory beanFactory = this.beanFactory;
    if (beanFactory == null) {
        throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                "call 'refresh' before accessing beans via the ApplicationContext");
    }
    return beanFactory;
}ClassPathXmlApplicationContext 不但实现了 BeanFactory 接口,并且实现了其他的接口为容器扩展了功能如:消息国际化、资源解析器、事件发布、获取环境变量等功能。
构造函数时创建 ioc 容器的入口,代码如下:
public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {
    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}执行构造方法,每个 ApplicationContext 都有自己的实现,但是都会初始化容器状态标识 active、closed。
ClassPathXmlApplicationContext在执行构造方法时,并不会初始化beanFactory。而AnnotationConfigApplicationContext在初始化时并创建好beanFactory,并将internalConfigurationAnnotationProcessor、internalAutowiredAnnotationProcessor等几个后 bean 后处理器注入,用于解析@Configuration、@Autowired等注解。如果全部以xml的形式给容器注入 bean,那么是不需要这几个后处理器的,但是如果需要配置文件的方式也能使用注解,就需要配置<context:annotation-config/>
不管怎么说,都会执行 refresh() 方法用于刷新容器。其中 AbstractApplicationContext 的 refresh() 方法,代码如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // 执行刷新容器前的一些必要方法
        prepareRefresh();
        // 调用子类获取到 bean 工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 配置 bean 工厂,以增强功能
        prepareBeanFactory(beanFactory);
        try {
            // 修改和调整 Bean 的定义(默认没有实现)
            postProcessBeanFactory(beanFactory);
            // 调用后置处理器
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注册 BeanPostProcessor,用于修改和增强 bean 的功能
            registerBeanPostProcessors(beanFactory);
            // 为上下文初始化 Message 源,即对不同语言的消息体进行国际化处理
            initMessageSource();
            // 初始化容器事件传播器
            initApplicationEventMulticaster();
            // 调用子类的某些特殊 Bean 初始化方法
            onRefresh();
            // 为事件传播器注册事件监听器(这里用到了观察者模式)
            registerListeners();
            // 初始化 Bean,并对 lazy-init 属性进行处理
            finishBeanFactoryInitialization(beanFactory);
            // Last step: publish corresponding event.
            finishRefresh();
        }
        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            // 销毁创建的单态 Bean
            destroyBeans();
            // 取消 refresh 操作,重置容器的同步标识.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        }
        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}1. prepareRefresh
protected void prepareRefresh() {
    // 设置容器的启动时间,以便在刷新容器时进行时间跟踪
    this.startupDate = System.currentTimeMillis();
    // 容器在关闭时会设置该值为true,此时容器不能再进行一些初始化操作。
    this.closed.set(false);
    // 将容器的活动状态设置为true,表示容器当前处于活动状态。
    this.active.set(true);
    if (logger.isDebugEnabled()) {
        if (logger.isTraceEnabled()) {
            logger.trace("Refreshing " + this);
        }
        else {
            logger.debug("Refreshing " + getDisplayName());
        }
    }
    // 初始化容器中可能使用的占位符属性源,例如 ${some.property},确保这些占位符被正确解析和设置。(这里的属性包含 JVM 属性 systemProperties,和操作系统的环境变量 systemEnvironment)
    // 这是个空方法,是留给子类实现的。
    initPropertySources();
    // 验证所需要的属性都存在,否则抛出异常
    getEnvironment().validateRequiredProperties();
    // 设置监听器
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        // Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }
    this.earlyApplicationEvents = new LinkedHashSet<>();
}通过继承 ClassPathXmlApplicationContext 可以重写 initPropertySources() 方法,启动时校验必要参数。
public class MyInitApplicationContext extends ClassPathXmlApplicationContext {
    public MyInitApplicationContext(String configLocation) throws BeansException {
        super(configLocation);
    }
    @Override
    protected void initPropertySources() {
        super.initPropertySources();
        System.out.println("test");
        getEnvironment().setRequiredProperties("aaa");
    }
}2. obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    // 自己定义了抽象的 refreshBeanFactory() 方法,具体实现交给了自己的子类
    refreshBeanFactory();
    return getBeanFactory();
}
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;obtainFreshBeanFactory 方法用于创建 bean 工厂,调用 refreshBeanFactory 方法为一个抽象方法,需要子类自行实现。这里有一个好处,就是比如使用 xml 文件和注解方式,因为他们获取 bean 信息方式不同,可以通过自己重写该方法创建工厂。
refreshBeanFactory() 方法交由子类 AbstractRefreshableApplicationContext 实现:
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 如果已经建立了 IoC 容器,则销毁并关闭容器
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建 beanFactory 容器,DefaultListableBeanFactory 类实现了 ConfigurableListableBeanFactory 接口
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        // 添加一些自定义操作
        customizeBeanFactory(beanFactory);
        // 载入 BeanDefinition,在当前类中只定义了抽象的 loadBeanDefinitions() 方法,具体实现 调用子类容器
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}loadBeanDefinitions() 方法交由子类 AbstractXmlApplicationContext 实现:
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 创建用于从 Xml 中读取 BeanDefinition 的读取器
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    // 配置 BeanDefinition 的读取器
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    // 为 beanDefinition 读取器设置 资源加载器,由于本类的基类 AbstractApplicationContext
    // 继承了 DefaultResourceLoader,因此,本容器自身也是一个资源加载器
    beanDefinitionReader.setResourceLoader(this);
    // 设置 SAX 解析器,SAX(simple API for XML)是另一种 XML 解析方法。相比于 DOM,SAX 速度更快,占用内存更小。
    // 它逐行扫描文档,一边扫描一边解析。相比于先将整个 XML 文件扫描进内存,再进行解析的 DOM,SAX 可以在解析文档的
    // 任意时刻停止解析,但操作也比 DOM 复杂。
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    // 初始化
    initBeanDefinitionReader(beanDefinitionReader);
    // Bean 读取器真正实现加载的方法
    loadBeanDefinitions(beanDefinitionReader);
}读取 BeanDefinition 的真正方法:
/**
 * ClassPathXmlApplicationContext 与 FileSystemXmlApplicationContext 在这里的调用出现分歧,
 * 各自按不同的方式加载解析 Resource 资源,最后在具体的解析和 BeanDefinition 定位上又会殊途同归。
 */
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }
}3. prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置类加载器和属性、资源解析器
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
    // 注册 AwareProcessor,用来给实现了 xxxAware 接口的类扩展功能
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 是忽略指定接口类型的属性的自动注入,而通过其他方式实现注入(通过上面的 ApplicationContextAwareProcessor 进行属性注入)
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    // 用于动态注册某些类型的依赖,使其可以被 Spring 容器自动注入
    // 第一个参数为:希望注入的类型,第二个参数为当遇到这种希望注入的类型时,时间注入该对象
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);
    // 注册检测和解析实现 ApplicationListener 接口的后处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    // 检测是否包含特定 bean,有则加入对应的后处理器
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
    // 注册默认环境bean。environment、systemProperties、systemEnvironment
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}对 BeanFactory 进行各种功能填充。其实如果自己直接 new 一个 BeanFactory,再添加上某些组件,也能够实现一个简单的容器。
这里主要是设置了一些类加载器和属性、资源解析器,还注册了一些后处理器用户处理实现特定接口的类,还注册了几个环境单例 bean。
4. postProcessBeanFactory
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}postProcessBeanFactory 方法主要用于在 Spring 容器实例化 bean 之前,修改和调整 bean 的定义。默认没有实现,子类可以重写。(ClassPathXmlApplicationContext 的基类 AbstractApplicationContext 对该方法并没有实现)
该方法与下面的 invokeBeanFactoryPostProcessors 方法效果一样,都是可以直接操作 beanFactory,可以新增、修改 bean 的定义。
5. invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}调用各种 BeanFactoryPostProcessor,以实现对 bean 定义的新增和修改等,包括 spring 本身的和自己实现的 BeanFactoryPostProcessor 接口的类,通过委托 PostProcessorRegistrationDelegate 实现。
6. registerBeanPostProcessors
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}注册 BeanPostProcessor,同样通过委托 PostProcessorRegistrationDelegate 实现。(注意这里是注册,而不是执行)
| 特性 | BeanFactoryPostProcessor | BeanPostProcessor | 
|---|---|---|
| 执行时机 | 在 Bean 定义加载后、Bean 实例化之前。 | 在 Bean 实例化后、初始化方法之前或之后。 | 
| 作用范围 | 主要用来修改或定制 Bean 定义(如修改属性、构造函数参数等)。 | 主要用来修改或增强 Bean 实例的行为。 | 
| 执行对象 | 操作的是 BeanFactory和BeanDefinition,改变 Bean 的元数据。 | 操作的是已经实例化的 Bean 对象。 | 
| 修改内容 | 可以修改 Bean 的定义,如属性、依赖等。 | 可以修改实例化后的 Bean,增加自定义逻辑或增强功能。 | 
| 常见用途 | 修改 Bean 配置、条件注册 Bean、动态改变 Bean 定义。 | 增强 Bean 功能、AOP、日志记录、延迟初始化等。 | 
7. initMessageSource
protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // Make MessageSource aware of parent MessageSource.
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            if (hms.getParentMessageSource() == null) {
                // Only set parent context as parent MessageSource if no parent MessageSource
                // registered already.
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // Use empty MessageSource to be able to accept getMessage calls.
        DelegatingMessageSource dms = new DelegatingMessageSource();
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
        }
    }
}8. initApplicationEventMulticaster
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                    "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}事件广播器负责在应用程序中传递事件,确保事件可以从发布者传播到所有的监听者。这个方法的功能是确保容器中有一个有效的 ApplicationEventMulticaster,并根据容器中是否已经存在相应的 bean 来进行初始化。
9. onRefresh
protected void onRefresh() throws BeansException {
    // For subclasses: do nothing by default.
}空方法,用于留给子类进行扩展。
10. registerListeners
protected void registerListeners() {
    // Register statically specified listeners first.
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }
    // Publish early application events now that we finally have a multicaster...
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}所有注册的 bean 中查找监听器,注册到应用事件广播器中。
11. finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // 如果有的话,初始化默认转换服务。
    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
            beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
        beanFactory.setConversionService(
                beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
    }
    // 注册嵌入式值解析器,以支持占位符(placeholders)解析的功能。例如:${property.name}
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }
    // 初始化 LoadTimeWeaverAware 实例
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }
    // 停止使用临时类加载器,并将其清除。
    beanFactory.setTempClassLoader(null);
    // 锁定 beanFactory 配置。一旦进入这个阶段,Spring 假设所有的 Bean 定义已经准备就绪,锁定配置,以提升性能。
    // 1. 不再允许新增或修改 Bean 定义 2. 可以更高效地缓存元数据,例如 Bean 的依赖关系或类型信息。
    beanFactory.freezeConfiguration();
    // 实例化所有非延迟加载的 bean
    beanFactory.preInstantiateSingletons();
}初始化剩下的非懒加载实例,程序员自己编写的大部分 bean 都是在这里进行初始化的。在这里调用了 getBean 方法,创建了非惰性的 bean 实例。getBean 方法其中会调用 createBean 方法,毕竟 getBean 所需要获取的 bean 
这里具体就涉及到了 bean 的生命周期,比较复杂,可以当作另外一个探究的点。
12. finishRefresh
protected void finishRefresh() {
    // 清楚资源缓存
    clearResourceCaches();
    // 初始化生命周期处理器
    initLifecycleProcessor();
    // 触发生命周期处理器的刷新事件
    getLifecycleProcessor().onRefresh();
    // 发布上下文刷新事件
    publishEvent(new ContextRefreshedEvent(this));
    // 注册到 LiveBeansView
    // LiveBeansView 是 Spring 提供的工具类,用于调试和监控应用中定义的 bean。
    LiveBeansView.registerApplicationContext(this);
}提醒:本文发布于329天前,文中所关联的信息可能已发生改变,请知悉!
 
                         
                                    



