文章目录
Bean的实例化-循环依赖
循环依赖 如果存在A类中有B属性,B类中有A属性,那么当依赖注入的时候,就会产生当A类还没创建完成的时候,由于对B类的创建再次返回创建A类,最终造成循环依赖。
|
循环依赖的实例
类:CircularRelyA:
@Component
public class CircularRelyA {
@Autowired
private CircularRelyB mCircularRelyB;
}
类:CircularRelyB:
@Component
public class CircularRelyB {
@Autowired
private CircularRelyA mCircularRelyA;
}
循环依赖的相关方法
单例模式下的循环依赖流程
├─ getBean ① 实例化入口
│ ├─ doGetBean
│ │ ├─ getSingleton ② 查看缓存里是否有实例(本节重点方法)
│ │ ├─ getObjectForBeanInstance ③ 如果缓存有实例,直接返回实例
│ │ ├─ getSingleton ④ 缓存没有实例,创建实例(本节重点方法)
│ │ │ ├─ beforeSingletonCreation ⑤ 添加beanName到正在实例化的bean的set集,如果set中已存在当前beanName,则报错
│ │ │ ├─ createBean
│ │ │ │ ├─ doCreateBean ⑥ 执行创建实例
│ │ │ │ │ ├─ createBeanInstance ⑦ 创建实例过程
│ │ │ │ │ │ ├─ determineConstructorsFromBeanPostProcessors ⑧ 如果构造函数有@Autowired
│ │ │ │ │ │ │ ├─ autowireConstructor ⑨ 执行构造器实例过程 不会走到步骤 ⑪
│ │ │ │ │ │ │ │ └─ getBean 返回 ① 实例化入口
│ │ │ │ │ ├─ applyMergedBeanDefinitionPostProcessors ⑩ 注解的搜集和装配过程
│ │ │ │ │ ├─ earlySingletonExposure ⑪ 暴露还没有完全实例化完成的 bean
│ │ │ │ │ ├─ addSingletonFactory ⑫ 将提前暴露的 bean,放到三级缓存(本节重点方法)
│ │ │ │ │ ├─ populateBean ⑬ 注依赖注入的核心过程
│ │ │ │ │ │ ├─ inject
│ │ │ │ │ │ │ ├─ AutowiredFieldElement.inject ⑭ 有@Autowired注解域的注入
│ │ │ │ │ │ │ │ └─ getBean 返回①实例化入口
│ │ │ │ │ │ │ ├─ AutowiredMethodElement.inject ⑭ 有@Autowired注解方法的注入
│ │ │ │ │ │ │ │ └─ getBean 返回①实例化入口
│ │ │ │ │ ├─ initializeBean ⑮ bean 实例化和IOC依赖注入完以后的增强处理过程
│ │ │ │ │ └─ registerDisposableBeanIfNecessary ⑮ bean 的销毁过程
│ │ │ ├─ afterSingletonCreation ⑯ 实例化完成,将beanName从正在实例化的bean的set集合中删除
│ │ │ └─ addSingleton ⑰ 创建完成后,将完全实例化后的bean 放到一级缓存
循环依赖的步骤说明
CircularRelyA简称为 A,CircularRelyB简称为B,循环依赖步骤如下:
|
循环依赖中重点方法
getSingleton ()方法② 查看缓存里是否有实例
类文件:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 先从一级缓存中拿
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 一级缓存没有,并且不再创建中 则从二级缓存中拿
singletonObject = this.earlySingletonObjects.get(beanName);
//如果还拿不到,并且允许bean提前暴露
if (singletonObject == null && allowEarlyReference) {
// 二级缓存没有, 并且可以提前暴露的话, 则从三级缓存中获取ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// 如果三级缓存不为空
if (singletonFactory != null) {
// 调用的是AbstractAutowireCapableBeanFactory的getEarlyBeanReference方法
singletonObject = singletonFactory.getObject();
// 将对象放到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
// 删除三级缓存数据
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
getSingleton()方法④ 缓存没有实例,创建实例
类文件:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 先从一级缓存里面拿数据
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 如果要创建的bean在singletonsCurrentlyInCreation 中存在则报错
// 因为在这里的bean都未实例化完成
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 调用singletonFactory中的方法, 如果得到singletonObject,则表示已经彻底完成创建
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// bean创建完成后,从singletonsCurrentlyInCreation删除该bean
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 清除二级和三级缓存, 将Bean对象存到一级缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
有参数构造函数和多例循环依赖
有参构造函数循环依赖(报错失败)
有参构造函数循环依赖
|
多例模式循环依赖(报错失败)
和有参构造的思想比较相似,直接上doGetBean方法源码,可以看注释
类文件:org.springframework.beans.factory.support.AbstractBeanFactory
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 省略多例无关代码
// 多例模式, 查看prototypesCurrentlyInCreation中是否有当前beanName
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 省略多例无关代码
// 判断是否是多例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 将要创建的bean添加在prototypesCurrentlyInCreation 中
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
// 该方法是FactoryBean接口的调用入口
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 省略多例无关代码
}
循环依赖的流程图(Jack老师绘制)
循环依赖的补充说明
Bean的销毁
首先我们来看一下⑯ Bean的销毁过程
进入 doCreateBean ()方法
类文件:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
try {
...
//注册bean销毁时的类DisposableBeanAdapter
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
进入 registerDisposableBeanIfNecessary ()方法
类文件:org.springframework.beans.factory.support.AbstractBeanFactory
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
// 单例
if (mbd.isSingleton()) {
// 对该bean注册一个销毁的DisposableBeanAdapter对象,对给定的bean执行销毁工作 (@Destroy)
// DestructionAwareBeanPostProcessor 类型的接口
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
Bean的销毁如何被触发
1、在Spring 中执行显式关闭上下文,关闭时候会执行实现DisposableBean接口类中的destroy() 方法
@Test
public void testSpringStart() {
ConfigurableApplicationContext wApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
// 以下两种显式关闭都会调用实现了DisposableBean接口类中的destroy() 方法
// 1、显式关闭上下文
wApplicationContext.close();
// 2、显式关闭上下文
wApplicationContext.registerShutdownHook();
}
2、在Web环境中,当Tomcat关闭的时候就会调用到 servlet中的销毁方法,在这个方法中就会最终也会掉用到Spring中 DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。
servlet中的销毁方法
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
public void contextInitialized(ServletContextEvent event) {
this.initWebApplicationContext(event.getServletContext());
}
// servlet中的销毁方法
public void contextDestroyed(ServletContextEvent event) {
// 该方法最终会调用Spring的DisposableBeanAdapter类的destroy()
this.closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}