首先需要明确,这里调用的 refresh() 方法是 AnnotationConfigApplicationContext
上下文, obtainFreshBeanFactory()
获取的 beanFactory
实际类型是 DefaultListableBeanFactory
。
首先我们来看整体代码, refresh() 的方法很清晰,因为他将所有的功能封装到了各个方法中。后面我们会来一一介绍这些方法。
// 容器刷新的十二大步骤 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 容器启动的状态 StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); // Prepare this context for refreshing. // 1.准备上下文环境,作用就是初始化一些状态和属性,为后面的工作做准备。 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. /** 2. 工厂创建:BeanFactory 第一次开始创建的时候,有xml解析逻辑 * 2.1、创建BeanFactory对象 * 2.2、xml解析 * 传统标签解析:bean、import等 * 自定义标签解析 如:<context:component-scan base-package="org.example"/> * 自定义标签解析流程: * a、根据当前解析标签的头信息找到对应的namespaceUri * b、加载spring所以jar中的spring.handlers文件。并建立映射关系 * c、根据namespaceUri从映射关系中找到对应的实现了NamespaceHandler接口的类 * d、调用类的init方法,init方法是注册了各种自定义标签的解析类 * e、根据namespaceUri找到对应的解析类,然后调用paser方法完成标签解析 * 2.3、把解析出来的xml标签封装成BeanDefinition对象 */ ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 3. 预准备工厂,给容器中注册了环境信息作为单实例Bean 方便后续自动装配 // 并且放了一些后置处理器(监听、xxxAware功能) prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 4. 留给子类的模板方法,允许子类继续对工厂执行一些处理 postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); // Invoke factory processors registered as beans in the context. // 5. 【大核心】工厂增强:执行所有的BeanFactory 后置增强器 利用BeanFactory后置增强器对工厂进行修改或增强 // 配置类ConfigurationClassPostProcessor也会在这个解析 // BeanDefinitionRegistryPostProcessor BeanFactoryPostProcessor 完成对这两个接口的调用 invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 6. 【核心】注册 所有的Bean的后置处理器 registerBeanPostProcessors(beanFactory); beanPostProcess.end(); // Initialize message source for this context. // 7. 初始化国际化组件 initMessageSource(); // Initialize event multicaster for this context. // 8. 初始化事件派发 功能 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 9. 留给子类继续增强处理逻辑 // 这个方法着重理解模板设计模式,因为在springboot中,这个方法是用来做内嵌tomcat启动的 onRefresh(); // Check for listener beans and register them. // 10. 注册事件监听器,从容器中获取所有的ApplicationListener registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. /** * 11. 【大核心】bean创建:完成BeanFactory 初始化(工厂里面所有的组件都好了) * 这个方法一定要理解要具体看 * 11.1、bean实例化过程 * 11.2、ioc * 11.3、注解支持 * 11.4、BeanPostProcessor的执行 * 11.5、Aop的入口 */ finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // 12. 发布事件 finishRefresh(); } ... finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); contextRefresh.end(); } } } 复制代码
下面简单概括一下上面的初始化步骤:
prepareRefresh
: 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。在某些情况下项目的使用需要读取某些系统变量,那么在启动时候,就可以通过准备函数来进行参数的校验。obtainFreshBeanFactory
:初始化BeanFactory,并进行XML 文件读取(如果需要的话)。 这一步之后ApplicationContext就具有BeanFactory
所提供的功能,也就是可以进行Bean的提取等基础操作了。prepareBeanFactory
:对BeanFactory 进行各种功能填充。postProcessBeanFactory
: 对 BeanFactory 做额外处理。默认没有实现invokeBeanFactoryPostProcessors
: 激活各种BeanFactory 处理器(调用了各种BeanFactoryPostProcessor
)。其中最为关键的是ConfigurationClassPostProcessor
,在这里完成了配置类的解析,生成的注入容器中的bean 的 BeanDefinition。registerBeanPostProcessors
:注册和创建拦截bean创建的bean处理器。BeanPostProcessor
在这一步已经完成了创建。initMessageSource
:为上下文初始化Message 源,即对不同语言的消息体进行国际化处理initApplicationEventMulticaster
:初始化应用消息广播器,并放入"applicationEventMulticaster"
bean 中onRefresh
:留给子类来初始化其他beanregisterListeners
:在所有注册的bean中查找listener bean,注册到消息广播器中finishBeanFactoryInitialization
:初始化剩下的实例(非惰性),在这里调用了getBean方法,创建了非惰性的bean实例finishRefresh
:完成刷新过程,通知生命周期处理器lifecycleProcesseor
刷新过程,同时发出ContextRefreshEvent
通知别人。
1. 准备环境 - prepareRefresh()
prepareRefresh()
方法整体还是比较清晰的,作用就是初始化一些状态和属性,为后面的工作做准备。具体代码如下:
protected void prepareRefresh() { // Switch to active. // 设置启动时间,激活刷新状态 this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // Initialize any placeholder property sources in the context environment. // 其他子容器自行实现,留给子类覆盖 initPropertySources(); // Validate that all properties marked as required are resolvable: // see ConfigurablePropertyResolver#setRequiredProperties // 准备环境变量信息 getEnvironment().validateRequiredProperties(); // Store pre-refresh ApplicationListeners... // 存储子容器早期运行的一些监听器 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); } // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); } 复制代码
这里需要注意的两个方法:
initPropertySources() validateRequiredProperties()
我们可以通过实现或者继承 ApplicationContext 来重写这两个方法,从而完成一些基本属性的校验。
2. 加载BeanFactory - obtainFreshBeanFactory()
obtainFreshBeanFactory()
从字面意思就是获取BeanFactory。经过这个方法, BeanFactory
就已经被创建完成。具体代码如下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 刷新BeanFactory,注解模式下就是准备工厂,xml模式下会解析xml refreshBeanFactory(); return getBeanFactory(); } 复制代码
而实际上将 BeanFactory的创建委托给了 refreshBeanFactory()
方法, refreshBeanFactory()
方法被两个类实现 AbstractRefreshableApplicationContext