一、 Spring循环依赖问题
什么是循环引用:在A Service中引用了B,在B Service中引用了A,形成了一个闭环的情况。
spring为我们解决了这一个问题,前提是需要将bean的scope设置为singleton,如果设置为prototype则会报错,因为非单例的bean不会放入缓存中。spring主要是通过三级缓存来解决这个问题。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** 一级缓存,也叫单例池,存放已经经历完整声明周期的Bean */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** 三级缓存,存放可以生成bean的工厂 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** 二级缓存,存放早期暴露的bean,就是bean的属性尚未填装完毕 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
}
二、Spring循环依赖源码解读:
通过 ClassPathXmlApplicationContext 的构造方法进行了spring的初始化操作
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh(); // 这里进行了spring的初始化
}
}
进入refresh方法就可以看到spring的主要加载方法,
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 进行容器的初始化,并且加载bean
finishBeanFactoryInitialization(beanFactory);
}
}
这里主要看循环引用的地方
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
beanFactory.setTempClassLoader(null);
beanFactory.freezeConfiguration();
// 对所有的非懒加载的bean进行操作
beanFactory.preInstantiateSingletons();
}
进入到 preInstantiateSingletons 这个里
public void preInstantiateSingletons() throws BeansException {
// 从beanDefinition中获取需要加载bean的信息
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 加载bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 判断是否是抽象的,是不是单例,是不是懒加载
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
... // 代码省略 如果是工厂bean
}
else {
getBean(beanName); // 通过beanName获取bean
}
}
}
}
去获取bean,在spring中以do开头的方法一般都是真正处理的地方
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
这里只看单例bean的情况,因为只有单例bean才可以解决循环引用的问题。
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
// 检验是否存在alias 别名的配置
String beanName = transformedBeanName(name);
Object bean;
// 从一级缓存中查找
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 当循环引用的时候回走到这个分支,进行完善,返回bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
try {
// 通过beanDefine获取bean对象的信息
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 关于bean的依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
}
}
if (mbd.isSingleton()) {
// 只有单例模式,spring才会自动解决循环引用的问题,单例模式进行获取bean
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
}
return (T) bean;
}
首先,先看从一级缓存中查找
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
老规矩,继续翻,这里第一次进入,会直接返回null,主要是第二次循环引用来的时候。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从一级缓存中获取bean,刚开始肯定获取不到,直接返回null
Object singletonObject = this.singletonObjects.get(beanName);
// 判断一级缓存中是否有该bean,以及该bean是否正在被创建
// 当循环引用的时候 A-->B B-->A ,当A作为属性初始化的时,isSingletonCurrentlyInCreation这个返回的是false
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从二级缓存获取,此时肯定没有
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 从三级缓存获取,此时肯定有
ObjectFactory<?> singletonFactory =this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 这里执行的是之前存放的lambda表达式,代码说明放到最后
singletonObject = singletonFactory.getObject();
// 把A放到二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 把三级缓存的A删掉
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
为null返回以后继续向下走,到 getSingleton ,这里还传入一个lambda表达式
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
// 从一级缓存获取,第一次来根本获取不到
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
... // 代码省略
try {
// 这里直接到了createBean这个传入的方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 加入到单例池中,放在最后讲解
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
通过打断点可以知道getObject方法就是去执行传入的lambda表达式,createBean方法,Spring所有的后置处理器(BeanFactoryPostProcessor)所有的目的只有一个就是为了扩展实现。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
// 解决lookup method和 replace-up method的方法
mbdToUse.prepareMethodOverrides();
// 第一次应用spring的后置处理器 InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation
// 这里也是解析AOP并将AOP放入缓存的地方
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
这里主要就是将创建的bean放入三级缓存,并开始填充属性。
protected Object doCreateBean(...) throws BeanCreationException {
... // 代码省略
instanceWrapper = createBeanInstance(beanName, mbd, args);
if (instanceWrapper == null) {
// 第二次调用后置处理器,主要是解决使用哪个构造方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 第三个后置处理器,调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
... // 代码省略
// 是否是单例, allowCircularReferences 默认是true
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 主要是将创建的bean添加到三级缓存,并把lambda表达式也存起来
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
// 填装属性
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
首先,看如何初始化一个bean,直接到最后一行代码。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
... // 代码省略
// 调用 SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors后置处理器
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
... // 代码省略
return instantiateBean(beanName, mbd);
}
底层是通过反射创建的bean
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance;
if (System.getSecurityManager() != null) {
beanInstance = AccessController.doPrivileged(
(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
getAccessControlContext());
}
else {
// 初始化bean
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
}
}
}
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
... // 代码省略
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
// 反射获取到class对象
constructorToUse = clazz.getDeclaredConstructor();
}
return BeanUtils.instantiateClass(constructorToUse); // new一个对象
}
最后通过BeanUtil去调用newInstance
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
... // 代码省略
// 反射去创建对象
return ctor.newInstance(argsWithDefaultValues);
}
然后回过来看放入三级缓存
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {synchronized (this.singletonObjects) {
// 检查是否在一级缓存
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory); // 添加到三级缓存,并存lambda表达式
this.earlySingletonObjects.remove(beanName); // 从二级缓存移除
this.registeredSingletons.add(beanName);
}
}
开始填充属性
protected void populateBean(...) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 第五次调用后置处理器 InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;
// 判断是否要填装属性
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
// 获取属性
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 第六次调用后置处理器 主要是解决填装问题
// InstantiationAwareBeanPostProcessor的postProcessProperties
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp =(InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
// 属性填装
applyPropertyValues(beanName, mbd, bw, pvs);
}
protected void applyPropertyValues(...) {
// 用于存放相关联的属性
List<PropertyValue> original;
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
for (PropertyValue pv : original) {
// 如果service B 还没有创建那就去创建
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
}
// 属性赋值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
初始作为属性注入的bean
public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
... // 代码省略
}
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
// 判断是否有父工厂
if (ref.isToParent()) {...}
else{
// 判断有没有beanType,beanType 是ref的属性,ref是Service B,因为假设Service A引用 Service B,需要填装service B,B还没有初始化,在这里进行初始化
if (beanType != null) {...}
else {
resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
bean = this.beanFactory.getBean(resolvedName); // 这里又绕到了前面的doGetBean,获取到引用的A
}
}
}
这里又回到之前的getBean方法去创建B 这个Bean,当填充属性A bean的时候就会继续去获取bean A,但是这次能在三级缓存中获取到bean A于是在getSingleton 方法中走保存的lambda表达式。
protected Object getEarlyBeanReference(...) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 第四次执行后置处理器 SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
在填充完属性以后 initializeBean 中调用后置处理器,还有一个后置处理在销毁(close)的时候调用,一共九个后置处理器。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 执行所有实现了aware的接口,这里不会设置environment因为之前设置了忽略
// 只会对实现BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三个接口进行设置
invokeAwareMethods(beanName, bean);
if (mbd == null || !mbd.isSynthetic()) {
// 第七次后置处理器 BeanPostProcessor 的 postProcessBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
if (mbd == null || !mbd.isSynthetic()) {
// 第八次后置处理器 BeanPostProcessor 的 postProcessAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
最后会放入到单例池中,迁移到一级缓存
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject); // 放入到一级缓存
this.singletonFactories.remove(beanName); // 从二级缓存移除
this.earlySingletonObjects.remove(beanName); // 从三级缓存移除
this.registeredSingletons.add(beanName); // 添加注册bean
}
}
总之就是一个俄罗斯套娃的形式,具体如图:
※:关于三级缓存的问题,三级缓存的关键? 三级缓存能不能换成二级缓存?
三级缓存的关键是 实例化和初始化分开操作。
三级缓存的意义是存在代理,如果只用二级缓存的话(一个存放半成品,一个存放成品),如果要是有代理对象需要一层覆 盖掉原来的,所以又加了一层,形成三级(一个存放代理用于覆盖半成品,一个存放半成品,一个存放成品)。
在普通的循环依赖的情况下,三级缓存没有任何作用。三级缓存实际上跟Spring中的AOP相关。AOP场景下的getEarlyBeanReference 会拿到一个代理的对象,但是不确定有没有依赖,需不需要用到这个依赖对象,所以先给一个工厂放到三级缓存里。
这个工厂的目的在于延迟对实例化阶段生成的对象的代理,只有真正发生循环依赖的时候,才去提前生成代理对象,否则只会创建一个工厂并将其放入到三级缓存中,但是不会去通过这个工厂去真正创建对象。