三、 Spring Beans(续)
24. 解释Spring框架中bean的生命周期
Bean生命周期:指定的就是Bean从创建到销毁的整个过程:
分4大步:
第1到第3步均是发生在IOC加载过程中的,第四步发生在Spring容器关闭时
- 实例化
a. 通过反射去推断构造函数进行实例化
b. 实例工厂、 静态工厂 - 属性赋值
a. 解析自动装配(byname bytype constractor none @Autowired) DI的体现
b. 循环依赖 - 初始化
a. 调用XXXAware回调方法
b. 调用初始化生命周期回调(三种)
c. 如果bean实现aop 创建动态代理 - 销毁
a. 在spring容器关闭的时候进行调用
b. 调用销毁生命周期回调
25. Spring是如何解决Bean的循环依赖?
1. 什么是循环依赖
2. Spring是如何解决Bean的循环依赖的
如何解决:采用三级缓存解决,也就是3个map。
-
一级缓存:存储完整的Bean
-
三级缓存:
a. 缓存的是函数接口:通过lambda 把方法传进去( 把Bean的实例(纯净态的实例)和Bean名字传进去(aop创建) )
b. 不会立即调:(如果在实例化后立即调用的话:所有的aop 不管bean是否循环依赖都会在实例化后创建
proxy, 正常Bean 其实spring还是希望遵循生命周期在初始化创建动态代理, 只能循环依赖才创建)
c. 会在 ABA (第二次getBean(A) 才会去调用三级缓存(如果实现了aop才会创建动态代理,如果没有实现
依然返回的Bean的实例))
d. 在c过程之后,放入二级缓存(避免重复创建)
夺命连环问: -
二级缓存能不能解决循环依赖?
a. 如果只是死循环的问题: 一级缓存就可以解决 :无法避免在并发下获取不完整的Bean?
b. 二级缓存也可以解决循环依赖: 只不过如果出现重复循环依赖 会多次创建aop的动态代理 -
Spring有没有解决多例Bean的循环依赖?
a. 多例不会使用缓存进行存储(多例Bean每次使用都需要重新创建)
b. 不缓存早期对象就无法解决循环 -
Spring有没有解决构造函数参数Bean的循环依赖?
a. 构造函数的循环依赖也是会报错
b. 可以通过人工进行解决:@Lazy- i. 就不会立即创建依赖的bean了
- ii. 而是等到用到才通过动态代理进行创建
26. Spring如何避免在并发下获取不完整的Bean?
双重检查锁
为什么一级缓存不加到锁里面:
性能:因为一级缓存还有其他bean,避免获取其他已经创建好的Bean还要阻塞等待
线程1先检查一、二、三级缓存是否有bean(第一次肯定没有),接着线程1开始创建bean并锁住了二三级缓存,只有当线程1将对象存到一级缓存之后,才会解锁二级、三级缓存,但此时,因为线程1在将bean添加到一级缓存的同时,也remove了二级、三级缓存。因此线程2没有取到bean对象,再调用getSingleton(A,objectFactory)进行二次检查,这次在一级缓存就可以取到bean了。
27. BeanDefinition的加载过程:
28. 如何在Spring所有BeanDefinition注册完后做扩展?
通常可以使用beanFactoryPostProcessor 对已注册的BeanDefinition进行修改、
或者通过BeanDefinitionRegistryPostProcessor 再进行注册
在加了 beanDefinition.setScope(“prototype”);之后,user实例bean的创建由单例变成了多例。
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//对已注册的BeanDefinition进行修改
for (String beanDefinitionName:beanFactory.getBeanDefinitionNames()){
System.out.println(beanDefinitionName);
}
BeanDefinition beanDefinition=beanFactory.getBeanDefinition("user");
beanDefinition.setScope("prototype");
}
}
29. 如何在Spring所有Bean创建完后做扩展?
哪里才算所有的Bean创建完: new ApplicationContext()---->refresh()---->finishBeanFactoryInitialization(循环所有的BeanDefinition ,通过BeanFactory.getBean()生成所有的Bean) 这个循环结束之后所有的bean也就创建完了。
第一种方式:创建一个类实现SmartInitializingSingleton,在它的方法中做扩展
preInstantiateSingletons的部分代码
第一部分:循环所有的beanDefinition,利用beanFactory.getBean()创建所有的bean
第一二种方式的代码执行都是在该段代码之后
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
//第二部分:判断bean是不是SmartInitializingSingleton,如果是的,执行afterSingletonsInstantiated
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
举例
@Component
public class SmartInitExtend implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("所有单例bean已经创建,SmartInitializingSingleton");
}
}
第二种方式:通过监听事件
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
//发布了一个事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
if (!IN_NATIVE_IMAGE) {
LiveBeansView.registerApplicationContext(this);
}
}
监听事件
@Component
public class RefreshedEventListener {
@EventListener(ContextRefreshedEvent.class)
public void onApplicationEvent(ContextRefreshedEvent event){
System.out.println("所有单例bean已经创建,ContextRefreshedEvent");
}
}