Bean是Spring中最核心的东西,因为Spring就像是个大水桶,而Bean就像容器中的水,水桶脱离了水便也没有了用处。Bean没有任何特别之处,Spring的目的就是让我们的Bean能成为一个纯粹的POJO,这也是Spring所追求的。那么Bean的整个生命周期是个什么样子的呢?
Bean创建过程
Spring Bean的整体创建流程如下:
- 定义普通的JAVA类
- 将普通的JAVA类转化成Bean的定义-BeanDefinition
- 根据BeanDefinition创建出Spring Bean
这个地方肯定有一个疑问,为什么不能用class对象来创建Bean呢?因为在class对象仅仅能描述一个对象的创建,它不足以用来描述一个Spring bean,而对于是否为懒加载、是否是首要的、初始化方法是哪个、销毁方法是哪个,这个Spring中特有的属性在class对象中并没有,所有Spring就定义了BeanDefinition来完成bean的创建。
源码解析
我们想要将某些文件夹下的类放到Spring容器中去,简单的写法:
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
/*AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();*/
}
在跟踪AnnotationConfigApplicationContext的源码中,关键的一个方法是AbstractApplicationContext类中的refresh方法,这个方法中的内容就可以总结成上边的图Bean创建的整个过程,方法中具体的内容:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 这里会判断能否刷新,并且返回一个BeanFactory, 刷新不代表完全情况,主要是先执行Bean的销毁,然后重新生成一个BeanFactory,再在接下来的步骤中重新去扫描等等
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 准备BeanFactory
// 1. 设置BeanFactory的类加载器、SpringEL表达式解析器、类型转化注册器
// 2. 添加三个BeanPostProcessor,注意是具体的BeanPostProcessor实例对象
// 3. 记录ignoreDependencyInterface
// 4. 记录ResolvableDependency
// 5. 添加三个单例Bean
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 子类来设置一下BeanFactory
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
// BeanFactory准备好了之后,执行BeanFactoryPostProcessor,开始对BeanFactory进行处理
// 默认情况下:
// 此时beanFactory的beanDefinitionMap中有6个BeanDefinition,5个基础BeanDefinition+AppConfig的BeanDefinition
// 而这6个中只有一个BeanFactoryPostProcessor:ConfigurationClassPostProcessor
// 这里会执行ConfigurationClassPostProcessor进行@Component的扫描,扫描得到BeanDefinition,并注册到beanFactory中
// 注意:扫描的过程中可能又会扫描出其他的BeanFactoryPostProcessor,那么这些BeanFactoryPostProcessor也得在这一步执行
invokeBeanFactoryPostProcessors(beanFactory); // scanner.scan()
// Register bean processors that intercept bean creation.
// 将扫描到的BeanPostProcessors实例化并排序,并添加到BeanFactory的beanPostProcessors属性中去
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
// 设置ApplicationContext的MessageSource,要么是用户设置的,要么是DelegatingMessageSource
initMessageSource();
// Initialize event multicaster for this context.
// 设置ApplicationContext的applicationEventMulticaster,么是用户设置的,要么是SimpleApplicationEventMulticaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 给子类的模板方法
onRefresh();
// Check for listener beans and register them.
// 把定义的ApplicationListener的Bean对象,设置到ApplicationContext中去,并执行在此之前所发布的事件
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
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();
contextRefresh.end();
}
}
}
整个创建过程细化后的流程如下图:
参考了一些文章,Spring Bean的生命周期大致被分为了四个阶段,而在每个阶段的前后都会有很多的扩展点提供给你,方便你对不同流程时期的Bean做一些额外的操作,具体的内容本次不做介绍,后续会深入:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction
总结
原来换工作面试被问到Spring底层原理时很多的知识点都是百度上的流程图了解到的,回答时还是很心虚的,只是理解了Spring的表层,最精髓的内容还没有挖掘出来。最近断断续续的看了一段时间的Spring源码,真的体会到了其中的“深奥”,在使用的过程中,虽然我们只是简单的定义类,以及使用相关的注解或者配置文件就可以让程序跑起来,但这却是是Spring底层做了大量的工作来支撑我们的使用,真的很强大。
不积小流无以成江海,不积跬步无以至千里;知识的获取过程,有些时候需要我们静下心来,仔细认真的去研究、总结;源码解读的过程还很长,期待。