概览
测试代码
@Slf4j
@Data
public class A {
B b;
public void fun() {
log.info("A fun");
b.fun();
}
}
@Slf4j
@Data
public class B {
A a;
public void fun() {
log.info("B fun");
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("META-INF/cycle.reference.xml");
A a = (A)applicationContext.getBean("a");
a.fun();
}
}
resource目录中创建META-INF/cycle.reference.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="a" class="com.example.springbootdemo.test.cycle.reference.A" >
<property name="b" ref="b"/>
</bean>
<bean id="b" class="com.example.springbootdemo.test.cycle.reference.B" >
<property name="a" ref="a"/>
</bean>
</beans>
获取 Bean A
获取Bean入口:org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
创建Bean A
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
把实例A工厂缓存下来(三级缓存):
该对象工厂在后面会被用于返回实例A
填充实例A的属性
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
递归获取Bean B
获取Bean B
创建Bean B
填充实例B的属性
递归获取Bean A
再次进入doGetBean(A)
从缓存中获取实例A
这里用到了加载Bean A时缓存过的对象工厂
返回半成品实例A
Bean B 属性填充完成
Bean B 属性填充完成后,然后初始化,最后返回Bean B