3.2spring源码系列----循环依赖源码分析

盛开的太阳 2020-11-11 06:33:06
spring 源码 循环 系列 3.2spring


首先,我们在3.1 spring5源码系列--循环依赖 之 手写代码模拟spring循环依赖 中手写了循环依赖的实现. 这个实现就是模拟的spring的循环依赖. 目的是为了更容易理解spring源码.

下面我们就进入正题, 看看spring的循环依赖源码.

 

一、getBean整体流程

 

目标很明确了, 就是要看看spring如何解决循环依赖的. 

代码入口是refresh()#finishBeanFactoryInitialization(beanFactory);

二、拆解研究流程中的每一步

调用方法beanFactory.preInstantiateSingletons();实例化剩余的单例bean. 为什么是剩余的?很显然我们在上面已经实例化一部分了.比如配置类, postProcessor等.

2.1 入口

 1 @Override
2 public void preInstantiateSingletons() throws BeansException {
3 if (logger.isTraceEnabled()) {
4 logger.trace("Pre-instantiating singletons in " + this);
5  }
6
7
8 // 获取容器中所有bean定义的名字
9 List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
10
11 // Trigger initialization of all non-lazy singleton beans...
12 /**
13 * 第一步: 循环bean定义的name
14 */
15 for (String beanName : beanNames) {
16 // 获取bean定义
17 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
18 // 生产bean定义的条件: 不是抽象的, 是单例的, 不是懒加载的. 符合这个标准的, 最后才会调用getBean()生产bean
19 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
20 // 这里判断是不是工厂bean, 这里和BeanFactory不是一个意思, 判断当前这个bean是否实现了beanFactory的接口
21 if (isFactoryBean(beanName)) {
22 Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
23 if (bean instanceof FactoryBean) {
24 final FactoryBean<?> factory = (FactoryBean<?>) bean;
25  boolean isEagerInit;
26 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
27 isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
28 ((SmartFactoryBean<?>) factory)::isEagerInit,
29  getAccessControlContext());
30  }
31 else {
32 isEagerInit = (factory instanceof SmartFactoryBean &&
33 ((SmartFactoryBean<?>) factory).isEagerInit());
34  }
35 if (isEagerInit) {
36 // 获取bean
37  getBean(beanName);
38  }
39  }
40  }
41 else {
// 第二步: 调用bean定义 42 getBean(beanName); 43 } 44 } 45 } 46 47 // Trigger post-initialization callback for all applicable beans... 48 /** 49 * 循环bean定义的name 50 */ 51 for (String beanName : beanNames) { 52 // 从缓存中得到实例instance 53 Object singletonInstance = getSingleton(beanName); 54 if (singletonInstance instanceof SmartInitializingSingleton) { 55 final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; 56 if (System.getSecurityManager() != null) { 57 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 58 smartSingleton.afterSingletonsInstantiated(); 59 return null; 60 }, getAccessControlContext()); 61 } 62 else { 63 smartSingleton.afterSingletonsInstantiated(); 64 } 65 } 66 } 67 }

首先, 循环bean定义, 这和我们模拟spring循环的第一步是一样的. 

第二步: 判断从BeanDefinitionMap中取出来的这个bean是否满足生产bean的条件

我们注意代码注释中, 生产bean定义的条件: 不是抽象的, 是单例的, 不是懒加载的. 符合这个标准的, 最后才会调用getBean()生产bean

然后:调用getBean()

到目前为止,我们完成了上图源码图的第一部分:

 

 

 2.2 创建bean前的准备工作

接下来看看getBean().doGetBean()方法

 1 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
2  @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
3
4 // 第一步: 转换bean name. 在这里传入进来的name可能是别名, 也有可能是工厂bean的name, 所以在这里进行一个转换
5 final String beanName = transformedBeanName(name);
6  Object bean;
7
8 // Eagerly check singleton cache for manually registered singletons.
9 // 第二步: 尝试去缓存中获取对象, 如果没有获取到就创建bean
10 Object sharedInstance = getSingleton(beanName);
11 if (sharedInstance != null && args == null) {
12 if (logger.isTraceEnabled()) {
13 //判断当前类是否是正在创建中
14 if (isSingletonCurrentlyInCreation(beanName)) {
15 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
16 "' that is not fully initialized yet - a consequence of a circular reference");
17  }
18 else {
19 logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
20  }
21  }
22 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
23  }
24
25 else {
26 // Fail if we're already creating this bean instance:
27 // We're assumably within a circular reference.
28 /**
29 * 判断当前的bean是不是多例, 如果是这抛出异常
 30 *
31 * 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
32 * spring 只能解决单例对象的setter注入的循环依赖, 不能解决构造器注入
33 *
34 * 如果是多例的bean, 当前正在创建bean, 也会抛出异常---这也是循环依赖的问题
35 */
36 if (isPrototypeCurrentlyInCreation(beanName)) {
37 throw new BeanCurrentlyInCreationException(beanName);
38  }
39
40 /**
41 * 下面这段代码是关于子父容器的, 只有spring mvc继承自spring, 才会有子父容器的问题.
42 */
43 // Check if bean definition exists in this factory.
44 BeanFactory parentBeanFactory = getParentBeanFactory();
45 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
46 // Not found -> check parent.
47 String nameToLookup = originalBeanName(name);
48 if (parentBeanFactory instanceof AbstractBeanFactory) {
49 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
50  nameToLookup, requiredType, args, typeCheckOnly);
51  }
52 else if (args != null) {
53 // Delegation to parent with explicit args.
54 return (T) parentBeanFactory.getBean(nameToLookup, args);
55  }
56 else if (requiredType != null) {
57 // No args -> delegate to standard getBean method.
58 return parentBeanFactory.getBean(nameToLookup, requiredType);
59  }
60 else {
61 return (T) parentBeanFactory.getBean(nameToLookup);
62  }
63  }
64
65 /**
66 * 方法参数typeCheckOnly是用来判断#getBean()方法时, 表示是否为仅仅进行类型检查,
67 * 如果不仅仅做类型检查, 而是创建bean对象, 则需要调用#markBeanAsCreated(String name)
68 *
69 */
70 if (!typeCheckOnly) {
71  markBeanAsCreated(beanName);
72  }
73
74 try {
75 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
76  checkMergedBeanDefinition(mbd, beanName, args);
77
78 // Guarantee initialization of beans that the current bean depends on.
79 /**
80 * 现在有两个bean1, bean2 , 加载的时候调用的是bean1, bean2. 但如果我们想要bean2优先加载, 就使用@DependOn注解
81 * 用来解析带有dependOn注解的类
82 */
83 String[] dependsOn = mbd.getDependsOn();
84 if (dependsOn != null) {
85 for (String dep : dependsOn) {
86 if (isDependent(beanName, dep)) {
87 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
88 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
89  }
90  registerDependentBean(dep, beanName);
91 try {
92  getBean(dep);
93  }
94 catch (NoSuchBeanDefinitionException ex) {
95 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
96 "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
97  }
98  }
99  }
100
101 // Create bean instance.
102 /**
103 * 第三步: 创建单例bean实例
104 */
105 if (mbd.isSingleton()) { // 处理单例bean
106 /**
107 * 这里getSingleton()和上面的getSigleton不一样, 上面的是从一级缓存中拿.
108 * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要, 如果出现循环依赖, 发现bean正在创建, 就不会再创建了
109 */
110 sharedInstance = getSingleton(beanName, () -> {
111 try {
112 return createBean(beanName, mbd, args);
113  }
114 catch (BeansException ex) {
115 // Explicitly remove instance from singleton cache: It might have been put there
116 // eagerly by the creation process, to allow for circular reference resolution.
117 // Also remove any beans that received a temporary reference to the bean.
118  destroySingleton(beanName);
119 throw ex;
120  }
121  });
122 // 得到bean实例对象
123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124  }
125
126 else if (mbd.isPrototype()) { // 处理多例bean
127 // It's a prototype -> create a new instance.
128 Object prototypeInstance = null;
129 try {
130 // 当前正在创建多例bean
131  beforePrototypeCreation(beanName);
132 // 执行创建bean
133 prototypeInstance = createBean(beanName, mbd, args);
134  }
135 finally {
136  afterPrototypeCreation(beanName);
137  }
138 // 获取bean实例对象
139 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140  }
141
142 else { // 处理其他类型的bean
143 String scopeName = mbd.getScope();
144 final Scope scope = this.scopes.get(scopeName);
145 if (scope == null) {
146 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147  }
148 try {
149 Object scopedInstance = scope.get(beanName, () -> {
150  beforePrototypeCreation(beanName);
151 try {
152 return createBean(beanName, mbd, args);
153  }
154 finally {
155  afterPrototypeCreation(beanName);
156  }
157  });
158 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159  }
160 catch (IllegalStateException ex) {
161 throw new BeanCreationException(beanName,
162 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164  ex);
165  }
166  }
167  }
168 catch (BeansException ex) {
169  cleanupAfterBeanCreationFailure(beanName);
170 throw ex;
171  }
172 } 

 

在这里, 首先从缓存中获取bean, 看缓存中是否已经存在了

 Object sharedInstance = getSingleton(beanName);

然后, 如果缓存中已经存在了,那么久直接取出来. 代码如下: 

 if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
//判断当前bean是否是正在创建中(单例bean)
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的部分

首先, 判断是否是正在创建的多例bean, 如果是正在创建的多例bean, 就抛出异常,

已经是正在创建了, 说明这至少是第二次了, 这里处理的是单例bean的循环依赖, 不处理多例bean的循环依赖, 所以抛出异常

对应的代码是这一句

// Fail if we're already creating this bean instance:
27 // We're assumably within a circular reference.
28 /**
29 * 判断当前的bean是不是多例, 如果是这抛出异常
30 *
31 * 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
32 * spring 只能解决单例对象的setter注入的循环依赖, 不能解决构造器注入
33 *
34 * 如果是多例的bean, 当前正在创建bean, 也会抛出异常---这也是循环依赖的问题
35 */
36 if (isPrototypeCurrentlyInCreation(beanName)) {
37 throw new BeanCurrentlyInCreationException(beanName);
38 }

 

那么, 接下来就是首次创建bean. 首次创建的bean有三种情况:

第一种, 这个bean是单例的.

第二种, 这个bean是多例的.

第三种. 其他类型

对应的代码就是这一块. 有行号, 可以和上面一一对应上

// Create bean instance.
102 /**
103 * 第三步: 创建单例bean实例
104 */
105 if (mbd.isSingleton()) { // 处理单例bean
106 /**
107 * 这里getSingleton()和上面的getSigleton不一样, 上面的是从一级缓存中拿.
108 * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要, 如果出现循环依赖, 发现bean正在创建, 就不会再创建了
109 */
110 sharedInstance = getSingleton(beanName, () -> {
111 try {
112 return createBean(beanName, mbd, args);
113 }
114 catch (BeansException ex) {
115 // Explicitly remove instance from singleton cache: It might have been put there
116 // eagerly by the creation process, to allow for circular reference resolution.
117 // Also remove any beans that received a temporary reference to the bean.
118 destroySingleton(beanName);
119 throw ex;
120 }
121 });
122 // 得到bean实例对象
123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124 }
125
126 else if (mbd.isPrototype()) { // 处理多例bean
127 // It's a prototype -> create a new instance.
128 Object prototypeInstance = null;
129 try {
130 // 当前正在创建多例bean
131 beforePrototypeCreation(beanName);
132 // 执行创建bean
133 prototypeInstance = createBean(beanName, mbd, args);
134 }
135 finally {
136 afterPrototypeCreation(beanName);
137 }
138 // 获取bean实例对象
139 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
140 }
141
142 else { // 处理其他类型的bean
143 String scopeName = mbd.getScope();
144 final Scope scope = this.scopes.get(scopeName);
145 if (scope == null) {
146 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
147 }
148 try {
149 Object scopedInstance = scope.get(beanName, () -> {
150 beforePrototypeCreation(beanName);
151 try {
152 return createBean(beanName, mbd, args);
153 }
154 finally {
155 afterPrototypeCreation(beanName);
156 }
157 });
158 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
159 }
160 catch (IllegalStateException ex) {
161 throw new BeanCreationException(beanName,
162 "Scope '" + scopeName + "' is not active for the current thread; consider " +
163 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
164 ex);
165 }
166 }

我们的重点研究对象是单例bean. 所以,重点看单例bean的实现

105  if (mbd.isSingleton()) { // 处理单例bean
106 /**
107 * 这里getSingleton()和上面的getSigleton不一样, 上面的是从一级缓存中拿.
108 * 这个getSingleton()就办了一件事: 将bean设置为正在创建的状态. 这个状态很重要, 如果出现循环依赖, 发现bean正在创建, 就不会再创建了
109 */
110 sharedInstance = getSingleton(beanName, () -> {
111 try {
112 return createBean(beanName, mbd, args);
113 }
114 catch (BeansException ex) {
115 // Explicitly remove instance from singleton cache: It might have been put there
116 // eagerly by the creation process, to allow for circular reference resolution.
117 // Also remove any beans that received a temporary reference to the bean.
118 destroySingleton(beanName);
119 throw ex;
120 }
121 });
122 // 得到bean实例对象
123 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
124 }

这里的重点是调用了getSingleton(beanName, FactoryObject); FactoryObject是一个接口. 定义了一个钩子方法getObject(). 

这个接口在这里这是进行了定义, 并不会执行. 什么时候执行呢? 后面调用的时候执行. 

下面来看看getSingleton()方法, 钩子方法也是在这里被调用的.

 1 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
2 Assert.notNull(beanName, "Bean name must not be null");
3 synchronized (this.singletonObjects) {
4 // 第一步: 从一级缓存中获取单例对象
5 Object singletonObject = this.singletonObjects.get(beanName);
6 if (singletonObject == null) {
7 if (this.singletonsCurrentlyInDestruction) {
8 throw new BeanCreationNotAllowedException(beanName,
9 "Singleton bean creation not allowed while singletons of this factory are in destruction " +
10 "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
11  }
12 if (logger.isDebugEnabled()) {
13 logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
14  }
15 // 第二步: 将bean添加到singletonsCurrentlyInCreation中, 表示bean正在创建
16  beforeSingletonCreation(beanName);
17 boolean newSingleton = false;
18 boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
19 if (recordSuppressedExceptions) {
20 this.suppressedExceptions = new LinkedHashSet<>();
21  }
22 try {
23 // 第三步: 这里调用getObject()钩子方法, 就会回调匿名函数, 调用singletonFactory的createBean()
24 singletonObject = singletonFactory.getObject();
25 newSingleton = true;
26  }
27 catch (IllegalStateException ex) {
28 // Has the singleton object implicitly appeared in the meantime ->
29 // if yes, proceed with it since the exception indicates that state.
30 singletonObject = this.singletonObjects.get(beanName);
31 if (singletonObject == null) {
32 throw ex;
33  }
34  }
35 catch (BeanCreationException ex) {
36 if (recordSuppressedExceptions) {
37 for (Exception suppressedException : this.suppressedExceptions) {
38  ex.addRelatedCause(suppressedException);
39  }
40  }
41 throw ex;
42  }
43 finally {
44 if (recordSuppressedExceptions) {
45 this.suppressedExceptions = null;
46  }
47  afterSingletonCreation(beanName);
48  }
49 if (newSingleton) {
50  addSingleton(beanName, singletonObject);
51  }
52  }
53 return singletonObject;
54  }
55 }

这里是调用getBean().

第一步: 去一级缓存中取成熟的单例bean. 如果拿到了, 就直接返回. 如果没拿到. 那么执行创建. 

第二步: 在创建之前, 先把这个bean放入到正在创建的单例bean集合中. 标记这个bean正在创建中

第三步: 就是调用钩子方法getObject()了. 这个方法的方法体是在上面定义的. 其内容是去创建实例

 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;
}
});

这里的代码逻辑是完成了创建之前的逻辑

2.3 创建bean 

下面看看创建bean的过程

 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) {
/**
* 第一步: 实例化
* 这里面的调用链非常深, 后面再看
* bean实例化有两种方式
* 1. 使用反射: 使用反射也有两种方式,
* a. 通过无参构造函数 (默认的方式)
* 从beanDefinition中可以得到beanClass,
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* clazz.newInstance();
* 这样就可以实例化bean了
*
* b. 通过有参函数.
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* Constractor con = class.getConstractor(args....)
* con.newInstance();
*
* 2. 使用工厂
* 我们使用@Bean的方式, 就是使用的工厂模式, 自己控制实例化过程
*
*/
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.
// 允许后置处理器修改已经合并的beanDefinition
 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;
}
}
/**
* 缓存单例bean到三级缓存中, 以防止循环依赖
* 判断是否是早期引用的bean, 如果是, 则允许提前暴露引用
* * 判断是否能够早起暴露的条件 * 1. 是单例 * 2. 允许循环依赖 * 3. 正在创建的bean */ 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"); } // 把我们的早期对象包装成一个singletonFactory对象, 该对象提供了getObject()方法, 把静态的bean放到三级缓存中去了. addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 第二步:填充属性, 给属性赋值(调用set方法) 这里也是调用的后置处理器 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) { // 去缓存中获取到我们的对象 由于传递的allowEarlyReference是false, 要求只能在一级二级缓存中取 // 正常的普通的bean(不存在循环依赖的bean) 创建的过程中, 不会把三级缓存提升到二级缓存中. 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, 实例化的方式有两种. 一种是通过反射, 另一种是通过动态代理

/**
* 第一步: 实例化
* 这里面的调用链非常深, 后面再看
* bean实例化有两种方式
* 1. 使用反射: 使用反射也有两种方式,
* a. 通过无参构造函数 (默认的方式)
* 从beanDefinition中可以得到beanClass,
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* clazz.newInstance();
* 这样就可以实例化bean了
*
* b. 通过有参函数.
* ClassName = BeanDefinition.beanClass
* Class clazz = Class.forName(ClassName);
* Constractor con = class.getConstractor(args....)
* con.newInstance();
*
* 2. 使用工厂
* 我们使用@Bean的方式, 就是使用的工厂模式, 自己控制实例化过程
*
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);

 

判断是否是早期暴露的bean. 满足早期暴露的bean的三个条件是

1. 是单例的

2. 允许循环依赖

3. bean已经是处在正在创建中的行列了.

 /* 判断是否能够早起暴露的条件
* 1. 是单例
* 2. 允许循环依赖
* 3. 正在创建的bean
*/
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName)); 

创建bean的第二步: 属性赋值

// 第二步:填充属性, 给属性赋值(调用set方法) 这里也是调用的后置处理器
populateBean(beanName, mbd, instanceWrapper);

在这里会判断, 是否带有@Autowired的属性. 分为两种一种是Name,一种是Type

@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 判断属性是否有Autowired注解
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// Autowired是根据名字或者根据类型
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
......
}

如果按照名字注入

 protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 调用getBean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Added autowiring by name from bean name '" + beanName +
"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
"' by name: no matching bean found");
}
}
}
}

会再次调用getBean方法. 构建bean. 这是就有可能出现循环依赖了. 

按类型注入也是一样的. 

只是解析bean的方式不同.

 

创建bean的第三步: 初始化

 // 第三步: 初始化.
exposedObject = initializeBean(beanName, exposedObject, mbd);

在初始化bean的时候, 会调用很多的aware. 还会调用init-method方法. 以及bean的后置处理器.

 

第四步:删除实例化和静态方法在缓存中的数据

 /**
* 初始化完成以后, 判断是否是早期的对象
* 是循环依赖. 才会走进这里来
*/
if (earlySingletonExposure) {
// 去缓存中获取到我们的对象 由于传递的allowEarlyReference是false, 要求只能在一级二级缓存中取
// 正常的普通的bean(不存在循环依赖的bean) 创建的过程中, 不会把三级缓存提升到二级缓存中.
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.");
}
}
}
}
removeSingletonIfCreatedForTypeCheckOnly调用方法, 删除缓存.

这既是getBean()整个的过程. 中间还有很多细节, 没有往里面深入的看, 因为spring代码非常的深, 看的太深就忘了我们的目标了. 结合之前手写的spring循环依赖的思想看, 还是可以看得懂的. 

 

 

三. 接下来有几个问题

问题1: 为什么需要二级缓存和三级缓存?

二级缓存用来存放早期的bean, 也就是没有被属性赋值和初始化的bean
三级缓存的主要作用是用来解耦. 解耦后异步调用, 三级缓存中保存的是钩子方法,也就是一个接口。在使用的时候调用bean的后置处理器

 

问题2:有没有解决构造函数的循环依赖

答案是没有. 因为构造函数是在实例化的时候构建的. 这个时候bean都还没有创建, 所以没有办法处理循环依赖.如果出现构造函数的循环依赖, 是会直接报错的..

 

问题3:有没有解决多例下的循环依赖

也是没有的, 因为我们会判断, 如果是多例, 那么会抛出异常

 1 /**
2 * 第二步: 判断当前bean是否是正在创建中的多例bean, 如果是就抛出异常
3 *
4 * 2. 判断当前这个bean是不是多例bean. 如果配置了@Scope("prototype") 就表示这是一个多例的bean
5 * spring 只能解决单例对象的setter注入的循环依赖, 不能解决构造器注入
6 *
7 * 如果是多例的bean, 当前正在创建bean, 也会抛出异常---这也是循环依赖的问题
8 */
9 if (isPrototypeCurrentlyInCreation(beanName)) {
10 throw new BeanCurrentlyInCreationException(beanName);
11 } 

 

版权声明
本文为[盛开的太阳]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/ITPower/p/13956880.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云