spring的ioc来解决循环依赖的问题,从AbstractBeanFactory#getBean方法来进行源码分析,spring的解决循环依赖的原理,能够从三个本地缓存Map集合进行调解,本篇文章打算从循环依赖的定义来解释,在结合源码进行分析。spring
最简单的例子,spring的循环依赖,就是类A依赖类B,类B依赖类A,他们之间就行成了循环依赖。这是最简答例子,依据此方案就能够依赖3个类相互依赖可能致使死循环的情况。看代码实现:缓存
`app
@Servcie
Class A {
@Autowired
private B b;
}
@Service
Class B {
@Autowired
private A a;
}
复制代码
IOC容器去加载bean的时候,按照顺序去加载,会优先加载beanA而后会注入beanB,发现beanB没被实例,接下来会加载beanB而后注入beanA,这时候发现beanA没被实例。致使整个过程造成死循环,程序会一直加载,最终致使内存溢出。spring解决方案,采用三级缓存的实现方案,在容器加载beanB的时候,发现beanB依赖beanA,容器会在加载beanA放入到早期缓存,并把这个早期beanA注入到beanB中,beanB完成实例。beanA也就能够完成实例化。ide
`源码分析
/** Cache of singleton objects: bean name to bean instance. */
//最终缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
//早期缓存,用于解决循环依赖
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
//存放bean工厂对象,用于解决循环依赖
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
复制代码
咱们直接从AbstractBeanFactory#doGetBean方法开始分析。 `post
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//对bean进行check ,若是bean已经被实例就直接返回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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
//。。。中间省略细节
// Create bean instance.
//根据bean的做用域去分析
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
//这是建立bean的方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the 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;
}
}
复制代码
` 上面是获取bean的过程,先是从缓存中获取bean,若是没有会去建立beanui
`this
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先从最终缓存获取实例
Object singletonObject = this.singletonObjects.get(beanName);
//判断beanName对应的bean是否正在建立中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从早期缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//获取相应的bean工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
//将刚实例的bean放入早期工厂中
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
复制代码
上面的源码中,doGetBean 所调用的方法 getSingleton(String)是一个空壳方法,其 主要逻辑在 getSingleton(String, boolean) 中。该方法逻辑比较简单,首先从 singletonObjects 缓存中获取 bean 实例。若未命中,再去 earlySingletonObjects 缓存中获取原始 bean 实例。若是仍未命中,则从 singletonFactory 缓存中获取 ObjectFactory 对象,而后再调用 getObject 方法获取原始 bean 实例的应用, 也就是早期引用。获取成功后,将该实例放入 earlySingletonObjects 缓存中,并将 ObjectFactory 对象从 singletonFactories 移除。看完这个方法,咱们再来看看 getSingleton(String, ObjectFactory) 方法,这个方法也是在 doGetBean 中被调用的。下面咱们继续往下跟踪doCreateBean方法 `spa
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//将bean实例化,而且包裹BeanWrapper对象中
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
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");
}
//将bean工厂对象加入到singletonFactories对象早期bean工厂
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//注入属性bean
populateBean(beanName, mbd, instanceWrapper);
//执行一些初始化参数例如BeanNameAware
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
复制代码
` 在建立bean的过程分为三个部分,①、建立原始bean实例createBeanInstance,②、添加原始对象工厂对象到singletonFactories,③、注入属性bean。下面这张图是摘自别人博客prototype
本篇文章是对整个ioc如何解决循环依赖的,其实本质就是ioc容器加载的核心部分,相应的bean生命周期的核心也能在本篇透析出来。以上就是ioc的讲解,本人能力有限,你们相互进步哟。