写在前面
憋了好几天了,在经历了感冒的悲伤之后,终于大脑变得清晰起来。在《聊聊Spring的IOC以及JVM的类加载》中,之前留下了一个坑,不知道大家还有没有印象。那就是一个考查源码时必然会问到的一个面试题 - -Spring循环依赖是如何解决的。今天,我们就来好好分析下这个话题,我会很细致的讲解。预计,本文会很长很长,希望大家有耐心,去读完,相信你读完之后,对于Spring的IOC部分将有更深的源码理解。采用我的逻辑去把这个问题去解读明白。大致分为以下几部分:
- 何为循环依赖?
- Spring管理bean对象
- Spring如何解决循环依赖
何为循环依赖
想要理解这个问题,那么首先呢,需要有基础的知识储备。那就是Spring的IOC。IOC,是控制反转,后来出现更容易的理解 DI,依赖注入。大致上就是,一个A对象内有一个B对象属性,无需A对象显式创建B对象,可以通过Spring容器进行注入B对象到A对象中。这便是依赖注入的含义。
循环依赖的出现,是因为A对象中依赖B对象作为其中属性,B对象中依赖A对象作为其中属性。如下图所示:
举个例子描述:
小明喜欢小红,小红喜欢小黑,小黑喜欢小丽,小丽喜欢小明,如果中间所有人都不放弃喜欢的人,那么每个人都将陷入爱情循环中,无法自拔。
类似于这种依赖关系,在自然界中屡见不鲜,因此,映射到我们java的对象世界中,就必然会存在。
那么,如何处理循环依赖,保证合理的程序运行,是我们需要思考的问题。Spring作为一个技术框架,必然考虑到了循环依赖的问题。
Spring管理Bean对象
理解Spring作为容器管理bean对象之前,我们可以尝试思考下,我们自主,如何实现对于依赖对象的注入
场景描述
现有一个场景,蜜蜂采蜜。蜜蜂是一个对象,蜜蜂采蜜,需要作用于花,因此依赖花的存在。
蜜蜂对象,代码如下:
public class Bee { /** * 性别 */ private String sex; /** * 年龄 */ private Integer age; @Autowired private Flower flower; /** * 采蜜 */ public void pickingHoney() { // 花产蜜 flower.product(); } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
上述代码,是Spring采用注解注入的方式实现。
那么,试想,如果不使用Spring,我们如何实现呢?
一直接简单粗暴地创建对象(可以实现,但是明显不符合自然界对象定义,因为蜜蜂不能创造出花这个对象)
public class Bee { /** * 性别 */ private String sex; /** * 年龄 */ private Integer age; /** * 采蜜 */ public void pickingHoney() { // 花产蜜 Flower flower = new Flower(); flower.product(); } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
二反射获取对象
/** * 采蜜 */ public void pickingHoney() { Class clazz = Class.forName("com.example.demo.test.Flower"); Flower flower = (Flower)clazz.getDeclaredConstructor().newInstance(); flower.product(); }
可见,相比第一种来说,第二种反射获取对象,很优雅的实现了对象的处理。
注:反射作为Java的一个典型技术,非常重要
上述示例代码,通过反射实现,获取类对象,然后创建类实例。且上述采用的类名形式,那么我们就可以通过配置文件读取、自定义注解等多种方式,来实现反射的实现。
有了上述的技术积累,我们可以很开心的完成第一步,反射获取对象,实现对象的注入。
再思考,在每个类对象中,处理反射逻辑,会造成代码的冗余,且会造成,对象的创建频繁,没法保证单一等问题。那么,通过学习设计模式中的单例模式、工厂模式,我们可以发现,如果应用上述设计模式,或许更优雅。就这样,我们慢慢贴近了Spring的实现。
Spring框架就是应用了各种设计模式,同时采用反射技术,来实现对象的创建、初始化等操作的。
Spring管理bean对象
- Bean对象定义方式
Bean对象的定义,正如我们掌握的,在Spring中,可以通过几种方式完成:
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.demo.test.A"> <property name="b" ref="b"></property> </bean> <bean id="b" class="com.example.demo.test.B"> <property name="a" ref="a"></property> </bean> </beans>
如代码展示,可以直接通过xml文件,管理bean对象,实现bean对象的定义,以及属性的注入
注解形式可以通过各类注解,比如@Component @Controller @Service 等等
- Bean对象读取
在Spring管理下,对于Bean对象的读取,会形成一个抽象层,BeanDefinitionReader,然后形成BeanDefinition,完成对于Bean对象描述的定义 - BeanFactory
Bean对象的创建,由创建工程BeanFactory完成。BeanFactory会完成BeanDefinition的转换,然后构建bean对象,完成bean对象的实例化、初始化。
工厂,通过反射技术,根据BeanDefinition创建Bean对象。 - FactoryBean
FactoryBean是特殊的BeanFactory - BeanFactoryPostPocessor
BeanFactory的后置处理器,完成BeanFactory创建后的一系列补充 - BeanPostPocessor
Bean对象初始化前后的处理
流程描述:
- Spring读取XML文件等形式对于Bean对象的定义,构建BeanDefinition
- Spring的BeanFactory,读取BeanDefinition,完成Bean对象的读取,通过反射技术进行实例化
- BeanFactoryPostPocessor作为BeanFactory的后置处理器,完成补充处理
- BeanPostPocessor - before 完成对于bean对象初始化前的对象处理
- BeanPostPocessor - after完成对于bean对象初始化后的对象处理
- context.getBean 进行bean对象的使用
通过以上的分析,我们掌握了,Spring对于bean对象的读取、创建实例化、初始化的过程。了解了这些,我们才能去看循环依赖的事情。如若不然,个人觉得理解循环依赖问题,就比较困难。
Spring如何解决循环依赖
当我们能够明确了上述学习之后,我想,我们可以进入到源码的世界中去分析了。
查看解决循环依赖,也就是了解Spring是如何对Bean对象进行实例化、初始化的。
知识点:
对象的创建分为两部分,一部分为实例化,此时,在堆内存中分配了内存空间,但是未对其属性进行赋值,另一部分为初始化,完成对于实例化后对象的属性的赋值操作。因此类对象在内存空间中,两种状态,实例化状态(实例化完成、未初始化),完全状态(实例化完成、初始化完成)
一切的开始
以XML文件为例,代码如下,进入debug模式,走起,跟上队伍!
public class SpringTestApplication { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); } }
第一站
进入到,上下文的处理构造器中,看代码,找重点。
public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { // 此处是我们的第一站 refresh(); } }
refresh方法,在AbstractApplicationContext内。代码内部,做了点什么事情呢,可以详细的看看代码注释。
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 完成准备,设置时间啊等等,我们无需太关心 prepareRefresh(); // 无需多关心 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // bean factory 创建前的准备阶段,对应我们上述图的流程 prepareBeanFactory(beanFactory); try { //BeanFactory的处理过程,跟我们的对象创建关系不大 开始 // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); //BeanFactory的处理过程,跟我们的对象创建关系不大 完成 // Instantiate all remaining (non-lazy-init) singletons. //实例化,所有的非懒加载的单例bean对象,可见第二站入口来了,开启 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
第二站,真正的入口
看这个前,我们有必要了解一个类对象,其中提供了三个缓存对象
DefaultSingletonBeanRegistry
/** 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. */ // 二级缓存 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
记住,对应的对象名,后续在源码中会依次出现。
回到第二站,查看相关源码,直接查看注释中中文标记点,继续追踪
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. // 实例化,所有的非懒加载的单例bean对象 beanFactory.preInstantiateSingletons(); }
DefaultListableBeanFactory
@Override public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // 根据BeanDefinition 获取bean定义信息 for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 首先 A对象 此处非抽象类 单例 非懒加载才能进入,A对象符合条件,进入 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(beanName); } } } else { //A对象 进入 getBean(beanName); } } } // 省略 }
AbstractBeanFactory
@Override public Object getBean(String name) throws BeansException { // Spring源码内 do开头,都是真正做事情的方法 return doGetBean(name, null, null, false); }
第三站 创建bean
AbstractBeanFactory
查看中文代码注释部分,快速定位。按照代码执行序号,查看逻辑。
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. // 1. 获取单例bean对象 第四站入口 Object sharedInstance = getSingleton(beanName); // 根据第四站代码分析,此时A对象为空,返回空,将继续执行 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 { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. // 3. 创建对象 if (mbd.isSingleton()) { // 进入方法 sharedInstance = getSingleton(beanName, () -> { try { // 5. 创建对象 实现A 对象实例 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; } } // 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; }
第四站
DefaultSingletonBeanRegistry
@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 2. // 一级缓存中查找,是否存在bean A对象,此时为空 Object singletonObject = this.singletonObjects.get(beanName); // 判断一级缓存为空并且是否在创建中,我们在知识点中提及,类对象两种状态,实例化、完全状态,此时均未发生,因此不会进入判断 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) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } // 直接返回 空对象 return singletonObject; }
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); // 4. 执行对象处理 synchronized (this.singletonObjects) { // 一级缓存中获取A 对象,无 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //进入判断 if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 获取对象 ObjectFactory<?> 通过匿名内部类执行,匿名内部类 ,获取到A实例化对象,此时A 为实例化状态,创建中 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; } }
- 执行匿名内部类 创建A 对象
AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //实例A创建 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. // 此处 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"); } //三级缓存,放入实例化对象A 此时A 未完全状态 缓存内状态,见代码下图示 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 6. 填充bean populateBean(beanName, mbd, instanceWrapper); 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); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
缓存内部状态
- 填充bean属性内容
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 省略 if (pvs != null) { //处理属性内容 applyPropertyValues(beanName, mbd, bw, pvs); } }
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { // 省略代码 // Create a deep copy, resolving any references for values. List<PropertyValue> deepCopy = new ArrayList<>(original.size()); boolean resolveNecessary = false; for (PropertyValue pv : original) { if (pv.isConverted()) { deepCopy.add(pv); } else { // B对象 String propertyName = pv.getName(); // 值为 null Object originalValue = pv.getValue(); if (originalValue == AutowiredPropertyMarker.INSTANCE) { Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod(); if (writeMethod == null) { throw new IllegalArgumentException("Autowire marker for property without write method: " + pv); } originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true); } // 7. 解决B对象 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; //省略代码 }
BeanDefinitionValueResolver
@Nullable public Object resolveValueIfNecessary(Object argName, @Nullable Object value) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; //B对象作为A对象属性值,类型为RuntimeBeanReference 进入判断,执行方法resolveReference return resolveReference(argName, ref); } // 省略代码
@Nullable private Object resolveReference(Object argName, RuntimeBeanReference ref) { try { Object bean; Class<?> beanType = ref.getBeanType(); if (ref.isToParent()) { BeanFactory parent = this.beanFactory.getParentBeanFactory(); if (parent == null) { throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Cannot resolve reference to bean " + ref + " in parent factory: no parent factory available"); } if (beanType != null) { bean = parent.getBean(beanType); } else { // A对象依赖B对象,获取B对象 bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName()))); } } //省略代码
开始B对象的获取
第五站 依赖对象 B生成
重新回到
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. //进入获取 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); } //省略代码
类似A对象的处理,此处忽略
最终到了,处理B对象属性A对象,上述描述6 。此时,缓存情况如下:
进一步补充属性,即完成B对象中属性A对象的获取。
重新进入doGetBean ,进入 getSingleton
@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 此时一级缓存中获取A对象,同样 A对象为空,此时一级缓存中不存在 Object singletonObject = this.singletonObjects.get(beanName); // A对象状态为 实例化 因此,在创建中,进入判断 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 二级缓存中获取 A对象 ,A对象为空,进入判断 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { //三级缓存中获取 A对象,可以读取到值 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); // 将A 对象放入 二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 将A 对象从三级缓存中删除 this.singletonFactories.remove(beanName); } } } } return singletonObject; }
此时,缓存情况如下:
处理完B对象的属性A对象后,B对象此时变为初始化完成、实例化完成,成为完全态
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) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 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) { // 8. A对象属性对象 B对象完成初始化后执行 addSingleton(beanName, singletonObject); } } return singletonObject; } }
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // 一级缓存放入 B对象 完全态 this.singletonObjects.put(beanName, singletonObject); // 三级缓存删除 B对象 this.singletonFactories.remove(beanName); // 二级缓存删除 B对象 this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
此时,缓存情况如下:
此时A对象中属性B对象,完成初始化,A对象会执行以下代码
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // 一级缓存放入 A对象 完全态 this.singletonObjects.put(beanName, singletonObject); // 三级缓存删除 A对象 this.singletonFactories.remove(beanName); // 二级缓存删除 A对象 this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
此时,缓存情况如下:
第六站 遍历Bean对象 B
@Override public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... // 根据BeanDefinition 获取bean定义信息 for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); // 首先 A对象 此处非抽象类 单例 非懒加载才能进入,A对象符合条件,进入 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(beanName); } } } else { //B对象 进入 getBean(beanName); } } } // 省略 }
故事结尾
最后直接返回,因为完全态在一级缓存中都存在了。
@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 从一级缓存中获取B对象,获取得到,直接返回 Object singletonObject = this.singletonObjects.get(beanName); 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) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }
终于结束了,带着大家走了一遍源码,不知道你能理解多少。
从以上源码,我们可以看到,Spring采用三级缓存,来实现循环依赖的解决。
常见的面试问题
- 循环依赖必须使用三级缓存么
其实,从我们解读看来,只需要把对象的两个状态处理好,就能处理好循环依赖的问题,因此实际上来说,不必要使用三级缓存对于一般的bean对象来讲。 - 为何Spring解决三级缓存要使用三级缓存,而不是二级缓存
为何Spring采用三级缓存,其实主要是因为Bean对象不仅仅是基础的一般对象,还会有一些AOP后期增强对象,通过Cglib或者JDK动态代理手段,织入的对象。二级缓存,只能满足一般Bean对象的处理,无法处理更多的对象。
再看三级缓存
/** 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. */ // 三级缓存 返回值类型 泛型为 ObjectFactory<?> 能够处理更多的事项 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name to bean instance. */ // 二级缓存 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
以上就比较明确,为何使用三级而不是二级了
总结
看源码就是需要细致认真的解读,因此需要耐心。希望读着也能有耐心看下去。如果你可以,我相信,你对于循环依赖,不会有什么难点。