前言:
关于Spring中Bean的声明周期的管理,网上有很多写的非常好的资源。但是由于我记性不好,看一次忘一次,索性自己在这里记一版简单版,用于面试的解释。
ps:该记录仅供参考,对错不负责任,如果大佬们发现有记录不对的地方,请及时私信或评论。
目录
前言:
Spring-Bean生命周期的两大过程。
Spring 加载bean对象的入口
重要方法解释
Spring-Bean声明周期的两大过程
从资源或者注解标注的类 到 BeanDefination对象;从BeanDefination对象到Bean对象
Spring 加载bean对象的入口首先说明一下,接口BeanFactory是整个Spring bean容器的入库。在该接口上的注释也说明了这一点:The root interface for accessing a Spring bean container。
但是BeanFactory只是一个接口,其实现是落在了他的实现类上,所以当Spring加载Bean对象时,会通过各种复杂的继承关系,最终将入口定位在类AbstractApplicationContext的refresh()方法上。(注:此refre()方法十分重要)
先附上源码:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 做准备,此方法可不深究
prepareRefresh();
// 重要方法一
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 补充beanFactory的设置
prepareBeanFactory(beanFactory);
try {
// 此方法可忽略
postProcessBeanFactory(beanFactory);
// 重要方法二
invokeBeanFactoryPostProcessors(beanFactory);
// 重要方法三:Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
... 忽略
// 重要方法四:实例化所有非延迟加载的bean
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);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
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();
}
}
}
重要方法一:obtainFreshBeanFactory
该方法的作用:解析xml配置文件并注册到BeanFactory中
- 创建beanFactory(这里创建的是DefaultListableBeanFactory);
- 通过调用loadBeanDefinitions(beanFactory)方法,扫描xml文件配置的bean信息转为beanDefinition对象,并通过BeanDefinitionRegistry注册到1.1的beanFactory中
- 得到所有spring相关的xml,将其转为document对象
- 解析document对象,并处理命名空间
- 注册beanDefinition对象到beanFactory中,并保留原始属性值(即:如果xml文件中
标签下的占位符,此时不做替换处理)。
- 该方法详细流程,可直接百度obtainFreshBeanFactory 方法 即可。
重要方法二:invokeBeanFactoryPostProcessors
该方法的作用:调用在上下文中注册为 bean 的BeanFactory增强器,即DefaultListableBeanFactory的增强器)
- 在方法PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(*,*)
替换beanDefinition对象的占位符为实际值,获取最终的BeanDefinition对象 - ,context:component-scan 标签的解析由ComponentScanBeanDefinitionParser进行解析,获取base-package值并解析成数组。然后创建ClassPathBeanDefinitionScanner ,由这个类来实现扫描包下的class和jar文件并把注解的Bean包装成BeanDefinition,
- 处理@ComponentScan、@import、@Bean等注解,生成BeanDefinition对象
- 将beanDefinition对象注册到Spring容器中。
至此,配置文件 到 BeanDefinition对象的转换结束。
重要方法三:finishBeanFactoryInitialization(beanFactory)
该方法作用:开始执行容器中的BeanDefinition对象 到Bean对象
先偷一张图:
图片摘自spring bean生命周期详解,源码分析_李晨璐的博客-CSDN博客
这张图可以简化一下:
- createBeanInstance():例化bean对象,分配内存,属性值设置为默认值 ,实例化后的对象被封装在BeanWrapper对象中
-
populateBean():用户自定义属性赋值,即Spring根据BeanDefinition中的信息 以及 通过BeanWrapper提供的设置属性的接口完成依赖注入。
-
InvokeAwareMethods():将 Spring 内部对象注入到 Bean 中,如BeanFactory、ApplicationContext、Environment、ReosurceLoader
-
其实到此处,bean对象已经创建完成可以使用了。但是Spring的优秀之处就在于他留下了很多可扩展的接口。
-
Bean的前置处理器:比如供dubbo框架扩展了@Service、@Reference注解的扫描
-
InvokeInitMethods:执行初始化的调用方法,在java中基本没啥用,但是会检测当前的bean对象是否实现了InitializingBean接口,如果实现了,会提供afterPropertiesSet()方法
-
Bean的后置处理器:后置处理器做了cglib和jdk代理的处理,固基于代理实现的aop可是看成是IOC的一个扩展



