Spring Bean的生命周期
Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式。
比如 singleton 单例作用域,就表示 Bean 在整个 Spring 中只有一份,它是全局共享的,当有人修改了这个值之后,那么另一个人读取到的就是被修改后的值。
Spring框架支持以下五种Bean的作用域:
-
singleton: 唯一 bean 实例,Spring 中的 bean 默认都是单例的。 -
prototype: 每次请求都会创建一个新的 bean 实例。 -
request: 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效 -
session: 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。 -
global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。缺省的Spring bean 的作用域是Singleton。
而 Spring 中的对象是 bean,bean 和普通的 Java 对象没什么区别,只不过 Spring 不再自己去 new 对象了,而是由 IOC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IOC 容器要即可,Spring Bean 的生命周期完全由容器控制。
它分为四个阶段:实例化 -> 属性赋值 -> 初始化 -> 销毁
org.springframework.context.support.AbstractApplicationContext.refresh()--> org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization // 初始化bean(延迟加载除外)--> org.springframework.beans.factory.config.ConfigurableListableBeanFactory.preInstantiateSingletons()--> org.springframework.beans.factory.support.AbstractBeanFactory.getBean--> org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean--> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean // 创建 bean(实例化 bean)--> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean

1、获取真正的BeanName:方法transformedBeanName()
-
去除 FactoryBean 的修饰符。如果 name 以 “&” 为前缀,那么会去掉该 “&”,例如,name = "&studentService",则会是 name = "studentService -
canonicalName方法:取指定的 alias 所表示的最终 beanName。
这里引入一个扩展点,Bean的alias是如何生成?key为别名、value是beanName ,而beanName的设置,源码如下:


那么alias最终会是:{"whiteApple3":"whiteApple2"} {"whiteApple3":"whiteApple1"}
2、获取缓存中的单例:getSingleton()
-
如果在缓存中可以单例, 有则进一步判断这个Bean是不是在创建中,如果是的就等待创建完毕,否则直接调用getObjectForBeanInstance()方法返回 -
如果在缓存中未存在单例,则继续下一步
-
parentBeanFactory不为空,并且containsBeanDefinition(beanName) 为false 则调用parentBeanFactory.doGetBean 返回Bean -
反之 继续下一步
5、getMergedLocalBeanDefinition() 将父类的BeanDefinition与子类的BeanDefinition进行合并覆盖
6、如果Bean是单例(singleton),则调用createBean() 创建bean
接下来,我们继续看 createBean。

1、mbd.isSingleton() 判断是否是单例,如果是,则需要在缓存factoryBeanInstanceCache 中把beanName对应的数据remove掉。 2、BeanWrapper为空的情况下 调用createBeanInstance创建bean实例。
如果是@Bean方式声明bean的创建,详见createBeanInstance – instantiateUsingFactoryMethod 方法。 bean如果没有有参构造器,默认使用无参的构造方法反射创建实例,详情见 createBeanInstance – instantiateBean方法。默认使用无参的构造方法:clazz.getDeclaredConstructor() 通过反射调用构造器创建对象:BeanUtils.instantiateClass(constructorToUse) 实例化对象 bean如果有唯一的有参构造器,并且参数能在Spring容器中找到,则通过有参构造器反射。详情见 createBeanInstance – autowireConstructor方法。
3、applyMergedBeanDefinitionPostProcessors:Bean后置处理器
CommonAnnotationBeanPostProcessor:负责@PostConstruct、@PreDestroy AutowiredAnnotationBeanPostProcessor :@Autowired、@Value ApplicationListenerDetector 暂不分析


为了解决循环引用问题,后续在单写章节聊这个点。
5、调用populateBean方法进行属性赋值
因为步骤3中applyMergedBeanDefinitionPostProcessors方法中,已经完成了属性数据的解析,当前此方法直接获取封装好的数据,进行处理即可。
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
//获取类中封装好的属性元数据
InjectionMetadata metadata = this.findResourceMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
return pvs;
} catch (Throwable var6) {
throw new BeanCreationException(beanName, "Injection of resource dependencies failed", var6);
}
}
6、调用initializeBean方法进行初始化
public void close() {
synchronized(this.startupShutdownMonitor) {
this.doClose();
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
} catch (IllegalStateException var4) {
}
}
}
}
8、扩展点:BeanPostProcessor
我们在学习的过程中,发现了很多继承BeanPostProcessor类的子类,因为spring bean在创建过程中不同的阶段都会回调BeanPostProcessor组件的方法,这样就可以达到扩展的目的。因为只要你自己实现了BeanPostProcessor组件,就可以在生命周期的不同阶段可以对你的bean进行不同的操作,达到自己的目的。
以上的分析,并没有很详细,只是描述个大概,每一个步骤的方法的背后需要深挖的点,都有很多,感兴趣的小伙伴,可自行查阅。
本篇文章来源于微信公众号: 技术小白逆袭指南
微信扫描下方的二维码阅读本文

Comments NOTHING