面试必问系列之最强源码分析,带你一步步弄清楚 Spring 如何解决循环依赖
- 2022 年 8 月 01 日
本文字数:17712 字
阅读完需:约 58 分钟
写在前面
憋了好几天了,在经历了感冒的悲伤之后,终于大脑变得清晰起来。考查源码时必然会问到的一个面试题 - -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);
以上就比较明确,为何使用三级而不是二级了
总结
看源码就是需要细致认真的解读,因此需要耐心。希望读着也能有耐心看下去。如果你可以,我相信,你对于循环依赖,不会有什么难点。
版权声明: 本文为 InfoQ 作者【小隐乐乐】的原创文章。
原文链接:【http://xie.infoq.cn/article/6b8edead68c7a908d54f4bf10】。文章转载请联系作者。
小隐乐乐
学会思考,才是进步的一大本质要求 2017.04.28 加入
公众号:进阶架构师 作者
评论