if (earlySingletonExposure) { // 这里暂时不介绍(毕竟 A 的流程暂时不会走完,先走完这一步的是 B 对象,而且两者的情况还不太一样) Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } elseif (!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()) { thrownew 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."); } } } }
protectedvoidpopulateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw){ // 判断 bean 实例是否存在 if (bw == null) { if (mbd.hasPropertyValues()) { thrownew 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. // InstantiationAwareBeanPostProcessors 接口实现回调,此时 bean 仅仅是实例化还未进行属性填充 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { // 可以指定是否进行接下来的属性填充 if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } }
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 获取当前 bean 的注入方式,由于是 bean 的创建,所以这里就是 0 (不需要注入) int resolvedAutowireMode = mbd.getResolvedAutowireMode(); 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; } // 判断是否存在后置处理器 boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) { // 这里着重注意 AutowiredAnnotationBeanPostProcessor 处理器,由它负责自动注入 PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); }
publicvoidinject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs)throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); // 遍历需要注入的元素,回到我们的例子,因为 A 有一个注入属性 B,所以这里注入的元素就是 B;对于 B 这里注入的元素就是 A if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { // 由于 B 属于字段注入,这里 element 的实现为内部类:AutowiredFieldElement element.inject(target, beanName, pvs); } } }
@Override protectedvoidinject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs)throws Throwable { // 获取需要注入的字段,本例中 bean A 对应 B;bean B 对应 A。 Field field = (Field) this.member; Object value; // 第一次肯定是没有缓存的 if (this.cached) { try { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } catch (NoSuchBeanDefinitionException ex) { // Unexpected removal of target bean for cached argument -> re-resolve value = resolveFieldValue(field, bean, beanName); } } else { // 主流程开始对字段 B 进行解析,这个阶段会触发 B 的构造,也就是调用 getBean() 完成 B 创建,而 B 同样有字段,所以又会回到本方法,只不过这里就要解析 B 的字段 A 了,那么又会触发 getBean 去构造 A,但是此时 A 已经处于三级缓存中了,那么就会将 A 从三级缓存中解析出来,存入二级缓存,完成 B 对象中 A 的注入。然后完成 B 对象的初始化,此时就会回到 A 的调用中来,value 就是已经初始化完成位于一级缓存中的 B,然后设置给 A。由于 A 还未初始化完成,所以 B 中的 A 由于指向了相同的引用,所以也是未初始化的。那么当字段设置完毕,就会继续 A 的初始化了,那么当 A 完成,B 中的 A 也自然是完整的对象。 value = resolveFieldValue(field, bean, beanName); } if (value != null) { // 设置访问权限,然后完成设置 ReflectionUtils.makeAccessible(field); field.set(bean, value); } }
对于 resolveFieldValue 方法,这里就不再进行展开了,感兴趣的读者可以自行查看源码,该方法会间接调用 getBean() 来完成 B 实例的构造。
总结
为了避免大家思绪混乱,我们总结一下当前发生了哪些过程: 1、getBean 方法第一调用,构造对象 A,将其包装之后存入三级缓存; 2、A 进行属性填充,发现 A 存在字段 B,而 B 也是 bean 对象,触发 B 的 getBean 调用; 3、调用 getBean 创建 B,然后将 B 进行包装存入三级缓存; 4、填充 B 的属性,发现 B 含有字段 A; 5、那么触发 A 的 getBean,完成 A 构造;
为了便于说明,我们再次回到 doGetBean 方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 此时由于 A 处于三级缓存中,那么 sharedInstance 就不会为 null 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 + "'"); } } // 因为 A 并非是 factoryBean,所以 beanInstance 就会直接返回完成 doGetBean 方法的调用 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
由于 getSingleton 方法已经存在 A 的实例,那么就会通过 A 对应的工厂方法拿到具体的 A 对象,然后将该实例存入二级缓存,同时从三级缓存中移除:
6、通过以上我们可以知道此时的 A 由于不需要代理,所以拿到的就是当初创建的 A 对象,然后将 A 从三级缓存移入到二级缓存,并注入到 B 中。其实通过循环依赖,我可能也可以看出,如果需要代理包装时,代理也并非第一次就创建出来,而是在需要用到该对象实例时,才会从三级缓冲中得到代理对象。 7、当 B 实例注入完 A 字段之后,那么就会结束 B 的属性填充阶段,接下来就是初始化阶段了。
初始化
我们继续上一阶段介绍,上一阶段中,A 对象到了属性填充阶段,而属性填充导致 B 的创建,B 的创建同样来到属性填充阶段,触发 A 的创建,当 B 完成 A 字段的注入之后也同样需要进行接下来的初始化。换而言之,A 在等待 B 的初始化完成然后再继续 A 的初始化。
if (earlySingletonExposure) { // 此时 beanName 为 B,而启用早期引用为 false,也就是说只从一级二级缓存中获取实例。还记得此时缓存的状态不?A 存在于二级缓存;而 A 获取 B 时,B 处于第一次创建,所以它还在三级缓存中。所以此时获取 B 为 null; 获取 A 时得到的就是二级缓存中的实例。既然这样,B 在注册完余下的钩子之后就结束了。另外如果缓存中存在这个对象,说明存在循环依赖,那么就需要慎重处理了 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { /* * 如果两者相等,说明在 initializeBean 阶段并没有代理产生,可以放心的返回。但是如果不想等,说明 exposedObject 被替换成了代理对象 */ if (exposedObject == bean) { exposedObject = earlySingletonReference; } // 既然对象被代理了,那么就需要检查是由有其他已经创建完成的 bean 依赖了当前对象(比如说:在属性填充阶段已经为 B 填充了对象 A,但是在初始化阶段,A 被替换成了代理对象了。那么显然 B 中的 A 与实际中的 A 并不相等,那不就出问题了) elseif (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { // 如果该对象用于实际的使用为目的,并非了类型检查,那么方法就会返回 false if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } // 如果集合不为空,那么就要报错了(你明明都已经注入完毕了,为啥突然又改变了) if (!actualDependentBeans.isEmpty()) { thrownew 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."); } } } } // 给定的 bean 是否仅仅为了类型检查 protectedbooleanremoveSingletonIfCreatedForTypeCheckOnly(String beanName){ // 如果一个 bean 并非为了类型检查而创建时,会被标记为已创建状态(被添加到 alreadyCreated 集合中),如果集合不存在,说明该 bean 除了类型检查没有其他目的,那么就返回 true;如果当前集合存在,说明该 bean 是作为实际使用的,那么返回 false if (!this.alreadyCreated.contains(beanName)) { removeSingleton(beanName); returntrue; } else { returnfalse; } }
一级缓存
什么时候转移至一级缓存呢?毕竟 B 当前处于三级缓存,A 处于二级缓存,接下来就介绍一级缓存的转换。