目录
前言
一直以来,只是知道 Spring
会解析所有的配置文件(通常我们会放在 resources
目录下),然后将从配置文件中解析到的 bean
定义封装成 BeanDefinition
,加载到 IOC
容器中。而不知道其内部是如何解析,执行的,本篇文章将予以揭秘
何时解析
要知道 spring
何时去解析配置文件,我们可以断定是在 IOC
容器启动时,那么我们可以根据 IOC
容器启动流程进行找寻
测试类
public class TransactionTest_2 {
public static void main(String[] args) {
/* 初始化启动 spring ioc 容器 */
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
/* 从 spring ioc 容器中获取一个 bean */
ProductInfoService productInfoService = (ProductInfoService) applicationContext.getBean("productInfoServiceImpl");
System.out.println("拿到的Bean为:" + productInfoService);
}
}
在第五行代码处打上断点,DEBUG
模式去调试
ClassPathXmlApplicationContext
的构造器
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
// 调用如下
this(new String[] {
configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
它的核心方法肯定就在 refresh()
方法里面,实际上它调用的是抽象类AbstractApplicationContext
的 refresh()
refresh()
方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/**
* 刷新上下文环境,初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验
*/
prepareRefresh();
// 该方法会解析所有 spring 配置文件(通常我们会放在 resources 目录下)
// 将配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* 为上下文准备BeanFactory,即对BeanFactory的各种功能进行填充,如常用的注解@Autowired @Qualifier等
* 设置SPEL表达式#{key}的解析器
* 设置资源编辑注册器,如PerpertyEditorSupper的支持
* 添加ApplicationContextAwareProcessor处理器
* 在依赖注入忽略实现*Aware的接口,如EnvironmentAware、ApplicationEventPublisherAware等
* 注册依赖,如一个bean的属性中含有ApplicationEventPublisher(beanFactory),则会将beanFactory的实例注入进去
*/
prepareBeanFactory(beanFactory);
try {
/**
* 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
* 在当前上下文使用的Bean容器BeanFactory的标准初始化完成后对其做一些修改。此时
* 所有的Bean definition都已经加载但是还没有 Bean 被创建
*/
postProcessBeanFactory(beanFactory);
/**
* 实例化和调用所有 BeanFactoryPostProcessor,包括其子类 BeanDefinitionRegistryPostProcessor
* 激活各种BeanFactory处理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor
* 执行对应的postProcessBeanDefinitionRegistry方法 和 postProcessBeanFactory方法
*/
invokeBeanFactoryPostProcessors(beanFactory);
/**
* 注册所有的 BeanPostProcessor,将所有实现了 BeanPostProcessor 接口的类加载到 BeanFactory 中
* 注册拦截Bean创建的Bean处理器,即注册BeanPostProcessor,不是BeanFactoryPostProcessor,注意两者的区别
* 注意,这里仅仅是注册,并不会执行对应的方法,将在bean的实例化时执行对应的方法
*/
registerBeanPostProcessors(beanFactory);
// 初始化上下文中的资源文件,如国际化文件的处理等
initMessageSource();
// 初始化上下文事件广播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher
initApplicationEventMulticaster();
// 给子类扩展初始化其他Bean
onRefresh();
// 注册监听器
registerListeners();
/**
* 设置转换器
* 注册一个默认的属性值解析器
* 冻结所有的bean定义,说明注册的bean定义将不能被修改或进一步的处理
* 初始化剩余的非惰性的bean,即初始化非延迟加载的bean
*/
finishBeanFactoryInitialization(beanFactory);
/**
* 初始化生命周期处理器DefaultLifecycleProcessor,DefaultLifecycleProcessor含有start方法和stop方法,spring启动的时候调用start方法开始生命周期,
* spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,启动有一直运行,如一直轮询kafka
* 启动所有实现了Lifecycle接口的类
* 通过spring的事件发布机制发布ContextRefreshedEvent事件,以保证对应的监听器做进一步的处理,即对那种在spring启动后需要处理的一些类,这些类实现了
* ApplicationListener<ContextRefreshedEvent> ,这里就是要触发这些类的执行(执行onApplicationEvent方法)另外,spring的内置Event有ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、RequestHandleEvent
* 完成初始化,通知生命周期处理器lifeCycleProcessor刷新过程,同时发出ContextRefreshEvent通知其他人
*/
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
obtainFreshBeanFactory()
方法会解析所有 spring
配置文件。在此也证明了我们的推断:在 IOC
容器启动时,会去解析所有的 spring
配置文件
obtainFreshBeanFactory()
方法
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 1.刷新 BeanFactory,并执行加载和解析配置文件的操作
refreshBeanFactory();
// 2.拿到刷新后的 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
refreshBeanFactory()
:刷新BeanFactory
,并执行加载和解析配置文件的操作getBeanFactory()
:拿到刷新后的BeanFactory
refreshBeanFactory()
方法
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
...
@Override
protected final void refreshBeanFactory() throws BeansException {
// 判断是否存在beanFactory
if (hasBeanFactory()) {
// 注销所有的单例 bean
destroyBeans();
// 重置beanFactory
closeBeanFactory();
}
try {
// 创建一个新的BeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 指定序列化id,如果需要的话,让这个BeanFactory从id反序列化到BeanFactory对象
beanFactory.setSerializationId(getId());
// 定制BeanFactory
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (