循环依赖终极讲解
课程内容
- 为什么要二级缓存和三级缓存
- 没有循环依赖不会访问二三级缓存的
- 二级缓存:将纯净的bean和成熟的bean做分离
- 二级缓存+两把锁解决多线程下获取到不完整的bean的问题
- 三级缓存:三级缓存的是函数式接口,调用我们的bean的后置处理器这里面会做实现AOP,主要用来做解耦
- Aop也可以二级缓存来解决
- 二级缓存+三级缓存:循环依赖下AOP的动态代理的问题
- Spring有没有解决构造函数的循环依赖
- 没有,因为构造函数在实例化当中,连实例都拿不到不能解决循环依赖;如果存在构造函数的循环依赖,会直接报错的
- Spring有没有解决多例下的循环依赖
- 多例bean不会存到缓存中,自然不会解决循环依赖
- 解决循环依赖的关键就是三级缓存,而三级缓存还解决了保证单例唯一性的问题。因为从缓存中取出来的实例是要保证bean是唯一的,所以三级缓存支持不了prototype。这也是prototype没有使用三级缓存而是简单的将bean的名字放到缓存当中的原因
- Spring读取不完整Bean的最终解决原理:Spring容器已经加载完之后,getbean时肯定是一个完整的bean,读取到不完整的bean的问题一定是Spring容器正在创建bean的过程当中,多个线程进来getBean所读取到的不完整的bean
- 二级缓存还是不能完整的解决Spring正在创建过程当中所出现的多线程读取到不完整的bean的
- 线程1: getBean(A)->getSingleton(A),返回null ->添加到正在创建集合中->实例化->存到三级缓存中->解析属性->发现A中依赖B->getBean(B).线程A停在这里
- 线程2: getBean(A)->getSingleton(A),一级缓存中仍然没有,但此时beanA已经标记为正在创建,在getSingleton()方法中会从二级缓存中拿(只有调用了三级缓存,才会去创建AOP实例或者拿到本身的实例,再存到二级缓存),此时二级缓存中仍然没有,从三级缓存中取,此时三级缓存中的beanA还没有解析完beanB
- 通过线程1和线程2可以得知仍然不能解决读取到不完整的bean的问题,要想解决这个问题就需要加两把锁
- 加锁之后的分析
- 线程1: getBean(A)->getSingleton(A),返回null ->加锁,添加到正在创建集合中->实例化->存到三级缓存中->解析属性->发现A中依赖B->getBean(B).线程A停在这里,仍在锁当中,线程A继续执行直到释放锁,线程B才能继续执行
- 线程2: getBean(A)->getSingleton(A),一级缓存中仍然没有,但此时beanA已经标记为正在创建->加锁,阻塞在这里
- DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)对一级缓存加了锁,直接锁住了整个创建过程
- DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)对一级缓存加了锁
- 二级缓存还是不能完整的解决Spring正在创建过程当中所出现的多线程读取到不完整的bean的
创建bean时在哪里创建了动态代理:初始化之后或者出现了循环依赖,实例化之后创建动态代理
为初始化对象创建动态代理,将这个代理对象放到二级缓存里面
正常情况下(正常的bean)会在初始化之后创建动态代理
只在循环依赖的情况下在实例化后创建动态代理:如何判断当前是不是循环依赖:singletonsCurrentlyInCreation集合
#DefaultListableBeanFactory
@Override
public void preInstantiateSingletons() throws BeansException {
if (logger.isTraceEnabled()) {
logger.trace("Pre-instantiating singletons in " + this);
}
//获取我们容器中所有bean定义的名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 循环我们所有的bean定义名称
for (String beanName : beanNames) {
//合并我们得bean定义,转换为统一的RootBeanDefinition类型,方便后续处理
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//根据bean定义判断是不是抽象的&&不是单例的&&不是懒加载的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(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());
}
if (isEagerInit) {
//调用真正的getBean的流程
getBean(beanName);
}
}
}
else {
//非工厂bean.就是普通的bean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//在这里传入的name可能是别名,也有可能是工厂bean的name,所以需要在这里转换
final String beanName = transformedBeanName(name);
Object bean;
//尝试去缓冲中获取对象
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//如果sharedInstance是普通的单例bean,下面的方法会直接返回,但如果sharedInstance是Factory类型的bean,则需要调用getObject工厂方法获取真正的bean实例.如果用户想获取FactoryBean本身,这里也不会做特别的处理,直接返回即可.毕竟FactoryBean的实现类本身也是一种bean,只不过具有特殊的功能而已.
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//spring只能解决单例对象的setter注入的循环以来,不能解决构造器注入
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
//若存在父工厂且当前的bean工厂不存在当前的bean定义,那么bean定义一定是存在父beanFactory
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//获取bean的原始名称
String nameToLookup = originalBeanName(name);
//若为AbstractBeanFactory类型,委托父类处理
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 委托给构造函数getBean()处理
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
//没有args,委托给标准的getBean()处理
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//方法参数typeCheckOnly,是用来判断调用#getBean(...)方法时,标识是否为仅仅进行类型检查
//如果不是仅仅做类型检查,而是创建Bean对象,则需要调用#markBeanAsCreated(beanName)
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
//处理dependsOn的依赖(这个不是我们的所谓的循环依赖,而是bean创建前后的依赖)
// 依赖bean的名称
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
//若给定的依赖Bean已经注册为依赖给定的bean,及循环依赖的情况:抛出BeanCreationException异常
for (String dep : dependsOn) {
//beanName是当前正在创建的bean,dep是正在创建的bean的依赖的bean的名称
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//保存的是beanName之间的映射关系:依赖beanName->dep的集合
registerDependentBean(dep, beanName);
try {
//获取dependsOn的bean,优先加载这个bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建单例bean
if (mbd.isSingleton()) {
//如果beanName和一个singletonFactory传入一个回调对象用于回调
//在#getSingleton()方法中会将当前bean标记为正在创建
sharedInstance = getSingleton(beanName, () -> {
try {
//进入创建bean的逻辑
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
@Override
@Nullable
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//第一步:我们尝试去一级缓存(单例缓存池中去获取对象,一般情况下从该map获取的对象是直接可以使用的)
//IOC容器中初始化加载单实例bean的时候第一次进来的时候,该map一般返回空
Object singletonObject = this.singletonObjects.get(beanName);
//若在第一级缓存中没有获取到对象,并且singletonsCurrrentlyInCreation这个list包含该beanName,说明出现循环依赖
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//尝试从二级缓存中获取对象(二级缓存中的对象是一个早期对象)
//早期对象:就是bean刚刚调用了构造方法,还来不及给bena的属性进行赋值的对象(纯净bean),就是早期对象
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中也没有获取到对象,allowEarlyReference为true(参数是由上一个方法传递进来的)
if (singletonObject == null && allowEarlyReference) {
//直接从三级缓存中获取OjbectFactory对象,这个对象就是用来解决循环以来的关键所在
//在IOC后期的过程中,当bean调用了构造方法的时候,把早期对象包装成一个 //OjbectFactory暴露到三级缓存中
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//在这里通过暴露的OjbectFactory包装对象中,通过他的getObject()来获取
//在这个环节中会调用到getEarlyBeanReference()来进行后置处理
singletonObject = singletonFactory.getObject();
//把早期对象放置在二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//把ObjectFactory包装对象从三级缓存中删除掉
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
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) {
...
...
...
}
//在创建bean之前将该bean标记为正在创建
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化bean:这个过程其实是调用createBean()方法
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;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
//在创建bean之前将该bean标记为正在创建
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
#
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
举例说明
- A依赖B,A依赖C,C依赖A,B依赖A
1. for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//如果bean定义不是抽象的,是单例的,不是懒加载的,才会走getBean方法,此时beanName为A
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
getBean(beanName);
}
}
2. protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//尝试去缓冲中获取对象,此时一二三级缓存都为空
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//这里直接将增强A返回并且赋值给B中的属性
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//spring只能解决单例对象的setter注入的循环以来,不能解决构造器注入
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 创建单例bean
if (mbd.isSingleton()) {
//如果beanName和一个singletonFactory传入一个回调对象用于回调
//在#getSingleton()方法中会将当前bean标记为正在创建,放到singletonsCurrentlyInCreation.add(beanName)集合里面,后面会用来判断循环依赖,此时A被加入这个集合里面
//在回调完createBean(beanName, mbd, args)这个方法拿到这个返回值,将A加入到一次缓存中并且清除掉二三级缓存
sharedInstance = getSingleton(beanName, () -> {
try {
//进入创建bean的逻辑
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
3. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//因为A是单例,允许循环依赖,当前正在创建
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//将beanName为A的钩子方法放入到这个三级缓存里面
//将getEarlyBeanReference()放入到三级缓存里面,如果存在循环依赖的话会调用这个方法
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//在这里会创建B,走上面的流程,将B标记为正在创建,因为B依赖A,会去走创建A的流程,注意已经
//addSingletonFactory已将AB都加入里面,A会getSingleton()从三级缓存中拿出来,如果为A设置了动态代理,会对A进行增强,并且加到二级缓存里面,将增强A注入到B的属性上面,当B走完这个整个过程,同样在这个方法会对A中的B属性进行填充,此时A和B都会创建完成
//A依赖C,步骤和上面一样
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
return exposedObject;
}
4. 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);
//因为A现在只存到了三级缓存里面
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;
}
5. protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
//如果为A生成动态代理,在这里会为A实现这个功能
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}