Spring是如何解决循环依赖的呢?
java1234
共 47131字,需浏览 95分钟
·
2021-05-20 23:03
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
1、什么是循环依赖?
2、循环依赖的场景
2.1、构造器的循环依赖【spirng无法解决】
//A类
public Class A{
private B b;
pubcli A(B b){
this.b=b;
}
}
//B类
public Class B{
private A a;
public B(A a){
this. a=a;
}
}
<bean id="a" class="com.make.spring.A">
<constructor-arg name="b" ref="b"></constructor-arg>
</bean>
<bean id="b" class="com.make.spring.B">
<constructor-arg name="a" ref="a"></constructor-arg>
</bean>
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("springConstructor.xml");
A bean = context.getBean(A.class);
System.out.println(bean);
}
2.2、setter方法注入属性,singleton单例模式
public class A {
private B b;
public void setB(B b) {
this.b = b;
}
public B getB() {
return b;
}
}
public class B {
private A a;
public void setA(A a) {
this.a = a;
}
public A getA() {
return a;
}
}
<bean id="a" class="com.make.bean.A">
<property name="b" ref="b"></property>
</bean>
<bean id="b" class="com.make.bean.B">
<property name="a" ref="a"></property>
</bean>
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
A beanA =context.getBean(A.class);
System.out.println(beanA.getB());
B beanB=context.getBean(B.class);
System.out.println(beanB.getA());
}
2.3、setter方式,prototype原型模式【spirng无法解决】
<bean id="a" class="com.make.bean.A" scope="prototype">
<property name="b" ref="b"></property>
</bean>
<bean id="b" class="com.make.bean.B" scope="prototype">
<property name="a" ref="a"></property>
</bean>
3、单例setter方法注入—循环依赖解决方法
3.1、使用缓存解决循环依赖
3.1、三级缓存
/** 一级缓存
* 单例对象缓存:bean name --> bean的完整实例*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 三级缓存
* 保存BeanName于创建bean工程之间的缓存:bean name --> 对象工程,lambda表达式*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 二级缓存
* 保存单例对象的半成品:bean name--> 半成品bean(bean实例化好后,没有进行属性填充,没有初始化的半成品对象)*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
3.2、代码执行过程示意图
4、依赖注入具体执行方法
4.1、调用ClassPathXmlApplicationContext的构造方法
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
//存储spring配置文件的路径到本地
setConfigLocations(configLocations);
//判断是否需要需要重新刷新spring容器——ApplicationContext
if (refresh) {
//刷新spring容器,加载bean的核心方法,刷新spring上下文信息,定义了上下文加载流程——ApplicationContext
refresh();
}
}
4.2、进入到AbstractApplicationContext类的refresh()方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/**
* 1、设置容器的启动时间
* 2、设置活跃状态为true
* 3、设置关闭状态为false
* 4、获取Environment对象,并加载当前系统的属性到Environment对象中
* 5、准备监听器和时间的结合对象,默认为空的集合
*/
// Prepare this context for refreshing.
prepareRefresh();
//创建容器对象:DefaultListableBeanFactory
//加载xml文件的属性,最终要的就是BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//beanFacotry的准备工作,对各种属性进行填充
prepareBeanFactory(beanFactory);
try {
//子类覆盖方法做额外的处理,此出我们一般不做任何扩展工作,可以查看web的代码,是有具体实现
postProcessBeanFactory(beanFactory);
//调用Bean工厂的后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor 自定义以及spring内部的
registerBeanPostProcessors(beanFactory);
// 初始化此上下文的消息源
initMessageSource();
// 初始化事件监听多路广播器
initApplicationEventMulticaster();
// 留给子类来初始化其他的bean
onRefresh();
//在所有注册的bean中查找listener bean,注册到消息广播中
registerListeners();
//初始化剩下的单实例(非懒加载的)
finishBeanFactoryInitialization(beanFactory);
//完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过
finishRefresh();
}
........
}
4.3、进入到finishBeanFactoryInitialization方法
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
......
// Instantiate all remaining (non-lazy-init) singletons.
//实例化剩下的单例对象
beanFactory.preInstantiateSingletons();
}
4.4、进入到preInstantiateSingletons方法
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in " + this);
}
//将所有的BeanDefinition的名字创建一个集合,beanNames获取到的是[a,b]
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
//触发所有非延迟加载单例bean的初始化,遍历集合
for (String beanName : beanNames) {
//合并父类BeanDefinition
//Bean定义的公共抽象类是AbstractBeanDefinition,普通的bean在spring加载bean定义的时候,实例化出来的是GenericBeanDefinition,而Spring上下文
//所有bean用的AbstractBeanDefintion是RootBeanDefinition,这个时候需要转换一些,将非RootBeanDefinition转成RootBeanDefinition进行后续操作
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//条件判断,抽象,单例,非懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//判断是否实现了FactoryBean接口
if (isFactoryBean(beanName)) {
//根据&+beanName来获取具体的对象
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final 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());
}
//如果急切的希望初始化,通过beanName获取bean的实例
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
//如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
getBean(beanName);
}
}
}
//遍历beanNames,触发所有的SmartInitializingSingleton的后初始化毁掉
......
}
4.4.1、第一个判断
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
4.4.2、第二个判断
if (isFactoryBean(beanName)) {
......
}
else {
//如果beanName对应的bean不是FactoryBean,只是普通的bean,通过beanName获取bean实例
getBean(beanName);
}
4.5、进入到getBean方法
@Override
public Object getBean(String name) throws BeansException {
//此方法获取实际bean的方法,也是触发依赖注入的方法
return doGetBean(name, null, null, false);
}
4.6、进入到dogetBean方法
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//提取对应的beanName
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联——6.1
Object sharedInstance = getSingleton(beanName);
//如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
if (sharedInstance != null && args == null) {
.....
}
else {
//判断我们是不是正在创建这个实例,如果是失败,应该是在循环参考之内
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//检查该工厂中是否存在bean定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
.....
}
//如果不是做类型检查,那么就用创建bean,此处在集合中做一个记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//此处做了BeanDefinition对象的转换,当我们从xml文件中加载BeanDefinition对象的时候,封装的对象时GenericBeanDefinition,
//此处要做类型转换,如果是子类bean的话,去合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
......
// Create bean instance.
//创建bean的实例对象,这里都可mdb就是RootBeanDefinition,也就是bean相关的一些定义信息
if (mbd.isSingleton()) {
//返回以beanName的(原始)单例对象,如果尚未注册,使用singletonFactory创建并注册一个对象
sharedInstance = getSingleton(beanName, () -> {
try {
//为给定的合并后的BeanDefinition(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//显示地从单例缓存中删除实例,可能是由创建过程急切地放在那里,以允许循环引用解析,还要删除
//接收该bean临时引用的任何bean
//销毁给定的bean,如果找到响应的一次性bean实例,委托给destoryBean
destroySingleton(beanName);
//重新抛出ex
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
......
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
.....
return (T) bean;
}
4.6.1、先尝试从缓存中获取bean——getSingleton(beanName)
//提前检查单例缓存中是否有手动注册的单例对象
Object sharedInstance = getSingleton(beanName);
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例对象缓存中获取beanName对应的单例对象<<一级缓存>>
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//如果为空,则锁定全局变量并进行处理
synchronized (this.singletonObjects) {
//从早期单例对象缓存中获取单例对象(之所以被称为早期单例对象,是因为earlySingletonObjects里
// 的所有对象都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
singletonObject = this.earlySingletonObjects.get(beanName);
//如果早期单例对象缓存中也没有,并且允许创建早期单例对象引用
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
4.6.2、开始调用getSingleton(beanName,singleFacotry)
if (mbd.isSingleton()) {
//返回以beanName的(原始)单例对象,如果尚未注册,使用singletonFactory创建并注册一个对象
sharedInstance = getSingleton(beanName, () -> {
try {
//为给定的合并后的BeanDefinition(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
......
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
//如果beanName为null,抛出异常
Assert.notNull(beanName, "Bean name must not be null");
//使用单实例对象的高速缓冲Map作为锁,保证线程同步
synchronized (this.singletonObjects) {
//从单例对象的高速缓冲Map中获取beanName对应的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果获取到的为空
if (singletonObject == null) {
//如果当前在destorySingletons中
if (this.singletonsCurrentlyInDestruction) {
......
}
......
//创建单例之前的回调,默认实现将单例注册为当前正在创建中
beforeSingletonCreation(beanName);
......
try {
//从单例工厂中获取对象
singletonObject = singletonFactory.getObject();
//生成了新的单例对象的标记成true,表示生成了新的单例对象
newSingleton = true;
}
......
finally {
//如果没有抑制异常记录
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//创建单例后的回调,默认实现将单例标记为不在创建中
afterSingletonCreation(beanName);
}
//生成了新的单例对象
if (newSingleton) {
//将beanName和singletonObject的映射关系添加到该工厂的单例缓存中,也就是一级缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
4.7、进入到getBean方法
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
......
try {
//实际创建bean的调用
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
......
}
4.8、进入到doGetBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//这个beanWrapper是用来持有创建出来的Bean对象的
BeanWrapper instanceWrapper = null;
//获取factoryBean实例缓存
if (mbd.isSingleton()) {
//如果是单例对象,从factorybean实例缓存中移除当前bean的定义信息
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//如果实例为空
if (instanceWrapper == null) {
//实例化bean
//根据bean使用对应的策略创建新的实例,如:工厂方法,构造函数主动注入,简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//从包装类中获取原始bean
......
//运行beanPostProcessor去修改合并的beanDefinition
......
//缓存单例以便处理循环引用,即使是像BeanFactoryAware这样的生命周期接口触发的
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
......
//添加到缓存当中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//初始化bean实例
Object exposedObject = bean;
try {
//注入过程
populateBean(beanName, mbd, instanceWrapper);
// 将会触发postProcessBeforeInitialization和postProcessAfterInitialization
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
......
}
......
}
//注册完成依赖注入的Bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
.....
return exposedObject;
}
4.8.1、开始调用createBeanInstance(beanName, mbd, args);
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//解析calss
Class<?> beanClass = resolveBeanClass(mbd, beanName);
......
// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//判断是否有解析的构造方法或者工厂方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
//已经解析过的class构造器
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果解析过
if (resolved) {
......
}
//需要根据参数解析、确认构造器的函数(从Bean后处理器确定构造函数)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 解析的构造器不为空 || 注入类型为构造函数自动注入 || bean定义中有构造器参数 || 传入参数不为空
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
......
}
// No special handling: simply use no-arg constructor.
//使用默认构造器
return instantiateBean(beanName, mbd);
}
调用具体的创建bean的方式,有好几种,本例子采用的是//使用默认构造器 return instantiateBean(beanName, mbd); [具体看博客](https://blog.csdn.net/finalcola/article/details/81451019)
4.8.2、将实例化后的a放入到缓存中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
......
//添加到缓存当中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//使用singletonObjects进行加锁,保证线程安全
synchronized (this.singletonObjects) {
//如果单例对象的高速缓存【Bean名称-bean实例】没有beanName对象
if (!this.singletonObjects.containsKey(beanName)) {
//将beanName.singletonFactory放入到单例工厂的缓存当中【bean名称-ObjectFactory】
this.singletonFactories.put(beanName, singletonFactory);
//从早期单例对象的高速缓存【bean名称-bean实例】,移除beanName的相关缓存对象
this.earlySingletonObjects.remove(beanName);
//将beanName添加到已注册的单例集中
this.registeredSingletons.add(beanName);
}
}
}
4.9、调用方法populateBean注入属性
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 如果bean实例为空(空实例),并且其属性不为空,则抛出错误,否则跳过
......
// 在设置属性之前调用Bean的PostProcessor后置处理器
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
// 依赖注入开始,首先处理autowire自动装配的注入——因为我这里没有使用autowire所以省略
......
// 检查容器是否持有用于处理单态模式Bean关闭时的后置处理器
......
if (pvs != null) {
//主线
// 对属性进行注入操作,解决任何在这个bean工厂运行时其他bean的引用,必须使用深拷贝,所以不会永久修改这个属性
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
4.9.1、 调用设置xml属性的核心方法applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
//如果pvsPropertyValue
if (pvs.isEmpty()) {
//直接结束方法
return;
}
......
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
//遍历属性,将属性转换成对应类的对应属性类型
for (PropertyValue pv : original) {
//如果该属性已经被解析过
if (pv.isConverted()) {
//将pv添加到deepCopy中
deepCopy.add(pv);
}
//如果没有
else {
//获取属性名
String propertyName = pv.getName();
//获取未经类型转换的值
Object originalValue = pv.getValue();
//由valueResolver根据pv解析出originalValue所封装的对象
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
......
}
}
......
}
4.9.2、 调用resolveValueIfNecessary方法解决属性的值
@Nullable
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
//如果values是RuntimeBeanReference实例
if (value instanceof RuntimeBeanReference) {
//将value强转成RuntimeBeanReference对象
RuntimeBeanReference ref = (RuntimeBeanReference) value;
//解析出对应的ref所封装的bean元信息(bean名称和类型)的Bean对象
//处理引用
return resolveReference(argName, ref);
}
......
}
4.9.3、 调用解决属性的ref外部引用resolveReference方法
@Nullable
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
try {
//定义一个存储b对象的变量
Object bean;
//获取两一个bean引用的bean类型
String refName = ref.getBeanName();
refName = String.valueOf(doEvaluate(refName));
//如果引用来自父工厂
if (ref.isToParent()) {
......
}
else {
//获取resolvedName的bean对象
bean = this.beanFactory.getBean(refName);
//注册beanName与dependentBeanNamed的依赖关系到bean工厂
this.beanFactory.registerDependentBean(refName, this.beanName);
}
if (bean instanceof NullBean) {
bean = null;
}
return bean;
}
......
}
//获取resolvedName的bean对象
bean = this.beanFactory.getBean(refName);
4.10、创建b的过程
singletonObject = this.earlySingletonObjects.get(beanName);
//如果早期单例对象缓存中也没有,并且允许创建早期单例对象引用
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
// 将会触发postProcessBeforeInitialization和postProcessAfterInitialization
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 将会触发postProcessBeforeInitialization和postProcessAfterInitialization
exposedObject = initializeBean(beanName, exposedObject, mbd);
//生成了新的单例对象
if (newSingleton) {
//将beanName和singletonObject的映射关系添加到该工厂的单例缓存中,也就是一级缓存中
addSingleton(beanName, singletonObject);
}
//addSingleton方法内部执行
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//将映射关系添加到单例对象的高速缓冲中
this.singletonObjects.put(beanName, singletonObject);
//移除beanName在三级缓存中的数据——工厂缓存
this.singletonFactories.remove(beanName);
//移除beanName在二级缓存中的对象
this.earlySingletonObjects.remove(beanName);
//将beanName添加到已经注册的单例集中
this.registeredSingletons.add(beanName);
}
}
4.11、将a创建完成
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:
https://blog.csdn.net/make_1998/article/details/116693232
锋哥最新SpringCloud分布式电商秒杀课程发布
👇👇👇
👆长按上方微信二维码 2 秒
感谢点赞支持下哈
评论