DefaultListableBeanFactory
相关机制探索本文的分析以 DefaultListableBeanFactory
为对象。
spring-beans
依赖的版本为 5.0.9.RELEASE
。
DefaultSingletonBeanRegistry
private final Map singletonObjects
: 存放完全实例化并且属性赋值完成的 Bean
,可以直接使用(一级缓存);private final Map earlySingletonObjects
: 存放早期的单例的 bean
的引用,尚未配置属性(二级缓存);private final Map> singletonFactories
: 存放单例的工厂 (三级缓存);private final Set singletonsCurrentlyInCreation
: 当前正在被创建的 bean
的缓存,创建前(createBean
)放入,创建后移除;private boolean singletonsCurrentlyInDestruction
: 当前是否在销毁 singleton
对象,如果是的话,此时创建单例对象会报异常;private final Map disposableBeans
: 需要进行销毁操作的 bean
;AbstractBeanFactory
:
private final Set alreadyCreated
: 记录那些被创建了至少一次的 bean
名称;private final ThreadLocal
: 当前正在被创建的原型 bean
,泛型中可以是字符串类型,存 bean
名称,也可以是 Set
类型存多个原型的 bean
的名称;DefaultListableBeanFactory#preInstantiateSingletons
:实例化所有非抽象的,非延迟加载的单例 Bean
bean
名称列表,对每个名称,用 getBean(String)
方法获取 bean
bean
,如果是 SmartInitializingSingleton
类型就执行回调方法AbstractBeanFactory#doGetBean
: 获取 bean
, 如果 bean
不存在还会进行创建DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
: 从三级缓存中获取单例 bean
AbstractAutowireCapableBeanFactory#createBeanInstance
: 创建bean实例AbstractAutowireCapableBeanFactory#populateBean
: 为 bean
注入属性DefaultListableBeanFactory#destroySingletons
: 销毁所有的单例 bean
BeanFactory doGetBean
过程doGetBean
流程概览:
getSingleton(String beanName, ObjectFactory> singletonFactory)
流程概览:
polulateBean
方法执行流程:
BeanFactory#destroySingletons
销毁过程singletonsCurrentlyInDestruction
这个属性为 true
;disposableBeans
,调用其中的每个 bean
的销毁方法;bean
之前,先销毁其依赖,如果有循环依赖的情况,不影响(比如 A 依赖 B,B 又依赖 A,A先开始进入销毁方法,结果是 B销毁,A再销毁);两个相互依赖的类:
@Setter
@Getter
public class Man {
private String name;
private Woman wife;
@Override
public String toString() {
return "Man{" + "name='" + name + '\'' + ", wife=" + wife.getName() + '}';
}
}
@Setter
@Getter
public class Woman {
private String name;
private Man husband;
@Override
public String toString() {
return "Woman{" + "name='" + name + '\'' + ", husband=" + husband.getName() + '}';
}
}
手动注册 BeanDefinition
到容器中:
public class CycleDependencyByPropertyDemo {
@Test
public void autowireDemo(){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 通过代码注册bean
bindBeansByCode(beanFactory);
// 获取bean
Man man = (Man) beanFactory.getBean("man");
System.out.println(man);
}
private static void bindBeansByCode(BeanDefinitionRegistry beanDefinitionRegistry) {
// 注册man
GenericBeanDefinition manDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
.genericBeanDefinition(Man.class)
.addPropertyReference("wife", "woman")
.addPropertyValue("name", "Jack")
.getBeanDefinition();
// 注册woman
GenericBeanDefinition womanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
.genericBeanDefinition(Woman.class)
.addPropertyReference("husband", "man")
.addPropertyValue("name", "Alice")
.getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("man", manDefinition);
beanDefinitionRegistry.registerBeanDefinition("woman", womanDefinition);
}
}
执行结果:
Man{name='Jack', wife=Alice}
Process finished with exit code 0
结论:通过属性注入是没有循环依赖发生的。
解决这类循环依赖的关键在于:
bean
以 ObjectFactory
的方式提供在 private final Map> singletonFactories
(第三级缓存)属性中;getSingleton(String beanName, boolean allowEarlyReference)
中从第三级缓存中和第二级缓存中取还未创建完全的 bean
;DependsOn
关系的属性注入如果基于上述的例子加入 dependsOn
关系,就会导致异常,改造后代码如下
private static void bindBeansByCode(BeanDefinitionRegistry beanDefinitionRegistry) {
// 注册man
GenericBeanDefinition manDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
.genericBeanDefinition(Man.class)
.addPropertyReference("wife", "woman")
.addPropertyValue("name", "Jack")
+ .addDependsOn("woman")
.getBeanDefinition();
// 注册woman
GenericBeanDefinition womanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
.genericBeanDefinition(Woman.class)
.addPropertyReference("husband", "man")
.addPropertyValue("name", "Alice")
+ .addDependsOn("man")
.getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("man", manDefinition);
beanDefinitionRegistry.registerBeanDefinition("woman", womanDefinition);
}
输出如下:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'woman': Circular depends-on relationship between 'woman' and 'man'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at com.zmf.spring.bean.cycle.CycleDependencyByPropertyWithDependsOnDemo.autowireDemo(CycleDependencyByPropertyWithDependsOnDemo.java:21)
结论:带有DependsOn
关系就不能解决循环依赖
两个相互依赖的类如下:
@Setter
@Getter
public class ConMan {
private String name;
private ConWoman wife;
public ConMan(String name, ConWoman wife) {
this.name = name;
this.wife = wife;
}
@Override
public String toString() {
return "ConMan{" + "name='" + name + '\'' + ", wife=" + wife.getName() + '}';
}
}
@Setter
@Getter
public class ConWoman {
private String name;
private ConMan husband;
public ConWoman(String name, ConMan husband) {
this.name = name;
this.husband = husband;
}
@Override
public String toString() {
return "ConWoman{" + "name='" + name + '\'' + ", husband=" + husband.getName() + '}';
}
}
测试类 CycleDependencyByConstructorDemo
以构造器相互注入的形式实例化 bean
,代码如下:
public class CycleDependencyByConstructorDemo {
@Test
public void constructDemo(){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 通过代码注册bean
bindBeansByCode(beanFactory);
// 获取bean
ConMan man = (ConMan) beanFactory.getBean("man");
System.out.println(man);
}
private static void bindBeansByCode(BeanDefinitionRegistry beanDefinitionRegistry) {
// 注册man
GenericBeanDefinition manDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
.genericBeanDefinition(ConMan.class)
.addPropertyValue("name", "Jack")
.addConstructorArgValue("Jack")
.addConstructorArgReference("woman")
.getBeanDefinition();
// 注册woman
GenericBeanDefinition womanDefinition = (GenericBeanDefinition) BeanDefinitionBuilder
.genericBeanDefinition(ConWoman.class)
.addConstructorArgValue("Alice")
.addConstructorArgReference("man")
.getBeanDefinition();
beanDefinitionRegistry.registerBeanDefinition("man", manDefinition);
beanDefinitionRegistry.registerBeanDefinition("woman", womanDefinition);
}
}
执行结果如下:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'man': Requested bean is currently in creation: Is there an unresolvable circular reference?
结论:构造器注入的循环依赖不能自动解决
Bean
生命周期手动注册BeanDefinition
spring中的三级缓存