Spring源码解析5——bean的加载(一)
1、加载bean的概述
当Spring将Xml配置文件的解析后,生成了BeanDefinition.interface类型的各种配置实例,如:GenericBeanDefinition.java等。接下来,就要解析BeanDefinition.interface类型的各种配置,生成我们需要的实例。
AbstractBeanFactory.java
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
AbstractBeanFactory.java
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
//转换name->beanName,规则:1、name中第一个字符如果有&符号,剔除&符号;
// 2、在aliasMap中找1规则name的value值,再用value作为key,循环查找,直到value=null,返回value=null时的key值。
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
/*
* 检查缓存中或者实例工厂中是否有对应的实例,会为什么首先会使用这段代码呢:
1、因为在创建单例bean 的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
Spring 创建 bean 的原则是不等bean 创建完成就会将创建bean 的ObjectFactory 提早曝光,也就是将ObjectFactory 加入到缓存中,
一旦下一个bean 在创建时要依赖上个bean,则直接使用ObjectFactory
* */
//2、直接尝试从缓存或者HashMap:singletonFactories 中的ObjectFactory 中获取
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身,而是返回指定方法返回的实例
//sharedInstance记录的只是原始的bean状态,并不一定是我们最终想要的bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//只有在单例情况下,才会尝试解决循环依赖,而在原型模式的情况下,如果存在:A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生:
// 当A还未创建完,就去创建B而再次返回创建A,造成循环依赖,也就是下面这种情况:原型模式的依赖检查
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则尝试从parentBeanFactory中检测
//containsBeanDefinition(beanName):检测当前加载的XML配置文件中是否包含beanName的配置
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 {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
//将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition
//如果指定的beanName是子Bean的话,会合并父类相关属性Text
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
//若存在依赖,则需要递归实例化依赖的Bean
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 {
//递归调用依赖的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
//依赖的bean实例化好之后,接下来实例化mbd本身
// Create bean instance.
//缓存中不存在已经加载的单例Bean,从头开始加载一个Bean
if (mbd.isSingleton()) {
//singleton模式创建Bean
sharedInstance = getSingleton(beanName, () -> {
try {
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()) {
//prototype模式创建Bean(new)
// 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 {
//指定的scope上实例化Bean
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
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.
//检查需要类型是否符合bean的实际类型。
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.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
对于加载过程,所涉及的步骤大致如下:
1.1、转换beanName

-
getBean("xxx")入参中含有"&xxx",去除&。
![clipboard]()
-
取指定alias表示的最后一个映射value。例如:aliasA->aliasB,aliasB->aliasC,最终返回aliasC。
![clipboard]()
1.2、尝试从缓存中加载单例
单例在Spring的同一个容器中只会被创建一次,后续再获取bean,就直接从单例缓存中获取。但是,缓存中可能会加载不到。如果加载不成功,spring则会从HashMap<String,ObjectFactory<?>:singletonFactories实例中加载。因为在创建单例bean的时候,会存在依赖注入的情况,为了避免循环依赖,Spring不等bean创建完,就会将创建Bean的ObjectFactroy<?>提前暴光在缓存中。


1.3、bean的实例化
如果从缓存中得到了bean 的原始状态,则需要对bean 进行实例化。这里有必要强调一下,缓存中记录的只是最原始的bean 状态, 井不一定是我们最终想要的bean 。举个例子,假如我们需要对工厂bean 进行处理,那么这里得到的其实是工厂bean 的初始状态,但是我们真正需要的是工厂bean 中定义的factory-method 方法中返回的bean ,而getObjectForBeanlnstance() 就是完成这个工作的,后续会详细讲解。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
//A:name没有前缀&,beanInstance是FactoryBean;
//B:name没有前缀&,beanInstance不是FactoryBean;
//C:name有前缀&,beanInstance是FactoryBean;
//D:name有前缀&,beanInstance不是FactoryBean;
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//如果指定的name是工厂相关的name(以&为前缀就是工厂相关的name)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
//如果beanInstance不是FactoryBean类型,检查不通过
//符合D
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//经过前面的判断,此处的beanInstance有两种可能:1、非FactoryBean,2、FactoryBean。
//符合B、C
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//可能1:符合A,beanInstance一定是FactoryBean
Object object = null;
if (mbd == null) {
//尝试从缓存中加载Bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
// containsBeanDefinition(beanName)是从beanDefinitionMap中,也就是所有以加载的类中检测是否定义了beanName
if (mbd == null && containsBeanDefinition(beanName)) {
//将存储XML配置文件的GenericBeanDefinition转换为RootBeanDefinition,如果指定的beanName是子Bean的话:
//同时会合并父类Bean的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
//是否是用户定义,而不是框架本身定义
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
1.4、原型模式的依赖检查
原型模式下不允许出现循环依赖,否则会抛出异常。

1.5、检测parentBeanFactory
containsBeanDefinition(beanName),它是在检测如果当前加载的XML 配置文件中不包含beanName 所对应的配置,就只能到parentBeanFactory 去尝试下了,然后再去递归的调用getBean() 函数。


1.6、将存储XML 配置文件的 GenericBeanDefinition.java类型 转换为RootBeanDefinition.java类型
主要为了后续传参方便。spring的设计中将BeanDefinition.interface类型实例的解析函数形参设计为了RootBeanDefinition.java类型。具体原因:可能是开始之初的设计,后续没有功能上的影响,所以没有改变BeanDefinition.interface类型实例的解析函数形参的类型。
1.7、寻找依赖
bean的初始化过程中,可能会用到某些属性,而某些属性可能是依赖于其他bean的,那么这个时候就有必要先加载依赖的bean。所以在spring加载顺寻中,初始化某个bean时候首先会初始化这个bean所对应的依赖。

第一步:
此处关系维护依赖关系的HashMap<String,Set<String>>:dependentBeanMap 是spring中很好的关系维护数据模型,可以让当前bean通过递归的方式查找依赖关系。


第二步:
在缓存依赖关系的Map中,加入依赖关系,此处的使用ConcurrentHashMap.java:computeIfAbsent()+Lambda表达式。


第三步:
递归调用依赖的Bean,先初始化当前bean所依赖的bean。
1.8、针对不同scope进行bean的创建
1.9、类型转换
2、FactroyBean的使用
一般情况下, Spring 通过反射机制利用bean 的class 属性指定实现类来实例化bean 。在某些情况下,实例化bean 过程比较复杂,如果按照传统的方式, 则需要在<bean> 中提供大量的配置信息,配置方式的灵活性受到限的,这时采用编码的方式可能会得到一个简单的方案。Spring 为此提供了一个org.Springframework.bean.factory. FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化bean 的逻辑。
FactoryBean 接口对于Spring 框架来说占有重要的地位, Spring 自身就提供了70 多个FactoryBean 的实现。它们隐藏了实例化一些复杂bean 的细节,给上层应用带来了便利。从Spring3.0 开始, FactoryBean 开始支持泛型,即接口声明改为FactoryBean<T>的形式:
package org.springframework.beans.factory;
import org.springframework.lang.Nullable;
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
该接口定义了以下3个方法:
- T getObject():返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中。
- boolean isSingleton():返回由FactoryBean创建的bean实例作用域是singleton还是prototype。
- Class<T> getObjectType():返回FactoryBean创建的bean类型
当配置文件中<bean>的class 属性配置的实现类是FactoryBean 时,通过getBean() 方法返回的不是FactoryBean 本身,而是FactoryBean#getObject() 方法所返回的对象,相当于FactoryBean#getObject () 代理了getBean() 方法。实际使用的例子如下:
- Car实例
package com.chelong;
public class Car {
private String type;
private String color;
private int speed;
//省略setter...getter
}
- 实现FactoryBean.interface接口,实现配置
package com.chelong;
import org.springframework.beans.factory.FactoryBean;
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo;
public Car getObject() throws Exception {
Car car = new Car();
String[] infos = carInfo.split(",");
car.setType(infos[0]);
car.setColor(infos[1]);
car.setSpeed(Integer.valueOf(infos[2]));
return car;
}
public Class<?> getObjectType() {
return null;
}
public String getCarInfo() {
return carInfo;
}
//接受","分割的carInfo属性。
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
- 定义配置文件spring-factory.xml(名称不固定)文件如下:
<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="car" class="com.chelong.CarFactoryBean" carInfo="兰博基尼,红色,20"/>
</beans>
当调用getBean ("car")时, Spring 通过反射机制发现CarFactoryBean 实现了FactoryBean的接口,这时Spring 容器就调用接口方法CarFactoryBean#getObjec()方法返回。如果希望获取CarFactoryBean 的实例,则需要在使用getBean(beanName) 方法时在beanName 前显示的加上"&"前缀,例如getBean("&car")。
3、缓存中获取单例bean(从缓存中获取ObjectFactory.java)

该部分获取缓存的单例bean在1.2中已经介绍过,接下来主要介绍一下各个Map的作用:
- singletonObjects:用于保存BeanName和创建bean实例之间的关系,beanName->beanInstance。
- singletonFactories:用于保存beanName和创建bean的工厂之间的关系,beanName->ObjectFactory。
- eralySingletonObjects:保存beanName和创建bean实例之间的关系。与singletonObjects的不同之处在于,当一个单例bean被放到里面后,那么当bean在创建过程中,就可以通过getBean()方法获取到,其目的就是用来检查循环依赖。
- registeredSingletons:用来保存当前所有已注册的bean。
4、从bean的实例中获取对象(从缓存中获取ObjectFactory.java)
对应1.3中的bean的实例化步骤:bean的实例化过程中,无论是从缓存中获得bean,还是根据不同的scope策略加载bean。总之,我们得到bean的实例后要做的第一件事就是调用getObjectForBeanlnstance()来检测一下正确性:如果当前获取的Object.java:sharedInstance是FactoryBean.java类型的bean,则调用该FactoryBean.java类型的实例的getObject()返回实例。

如果符合情形A,则将FactoryBean.java类型的实例解析交给了FactoryBeanRegistrySupport.java:getObjectFromFactoryBean()函数。

FactoryBeanRegistrySupport.java
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @param shouldPostProcess whether the bean is subject to post-processing
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//如果是单例模式
if (factory.isSingleton() && containsSingleton(beanName)) {
//对象锁,锁住ConcurrentHashMap<String,Object>:SingletonObjects对象
synchronized (getSingletonMutex()) {
//通过beanName从缓存获取已加载的实例
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
//对没有加载过的beanName进行加载
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
//同步问题:从缓存中再次获取,如果有已经加载过,可以直接拿过来使用
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
//如果还没有加载,将加载的对象放入factoryBeanObjectCache中
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
beforeSingletonCreation(beanName);
try {
//调用ObjectFactory的后处理器
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
FactoryBeanRegistrySupport.java
/**
* Obtain an object to expose from the given FactoryBean.
* @param factory the FactoryBean instance
* @param beanName the name of the bean
* @return the object obtained from the FactoryBean
* @throws BeanCreationException if FactoryBean object creation failed
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
//权限验证
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//直接调用getObject()方法
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
以上逻辑:
①、对于FactoryBean.java:getObject()
2中已经讲述了FactoryBean 的调用方法,如果bean 声明为FactoryBean 类型,则当提取bean 时提取的并不是FactoryBean ,而是FactoryBean.java 中对应的getObject() 方法返回的bean,而FactoryBeanRegistrySupport.java:doGetObjectFromFactoryBean() 正是实现这个功能的。
②、后处理器
除了调用FactoryBean.java:getObject() 方法后,并没有直接返回,而是调用了FactoryBeanRegistrySupport.java:postProcessObjectFromFactoryBean()处理。

这里,我们只需了解在Spring 获取bean 的规则中有这样一条: 尽可能保证所有bean 初始化后都会调用注册的BeanPostProcessor.java 的postProcessAfterlnitialization() 方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务逻辑。

5、获取单例bean(非缓存获取单例bean,重头开始加载)
如果缓存中不存在已经加载的单例,那么就需要重头开始加载单例bean,spring采用getSingleton()函数的重写(或叫重载,重载一般用在父子类的叫法),实现了bean的加载过程。
DefaultSingletonBeanRegistry.java
/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
* @param beanName the name of the bean
* @param singletonFactory the ObjectFactory to lazily create the singleton
* with, if necessary
* @return the registered singleton object
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//全局变量需要同步
synchronized (this.singletonObjects) {
//检查bean是否已经加载过,其实singleton模式就是复用已加载的Bean
Object singletonObject = this.singletonObjects.get(beanName);
//从已加载的记录中(singletonObjects)获取不到,则默认没加载bean
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 + "'");
}
//添加beanName到正在加载的队列中。
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//初始化Bean
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;
}
}
逻辑如下:
①、检查缓存中是否已经加载过。
②、加载单例的前处理方法:若缓存中没有加载,将当前加载的beanName添加到正在加载的bean的队列(Set<String>:singletonsCurrentlyInCreation)中。
③、通过ObjectFactory<?>.java中的getObject()方法加载bean的实例化对象。
④、加载单例的后处理方法:将当前加载的bean,从当前加载的bean队列(Set<String>:singletonsCurrentlyInCreation)中移除。
⑤、将结果记录至缓存。

上述代码中,只讲了bean加载所用到的实例时ObjectFactory.java类型,和加载实例的前后进行了一系列的操作,并没有将ObjectFactory.java类型的实例获取过程。

6、创建ObjectFactory<?>.java类型的实例(准备创建Bean)
AbstractAutowireCapableBeanFactory.java
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//锁定Class,根据设置的class属性或者根据className来解析Class
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
//验证及准备覆盖的方法,只是针对lookup-method和replace-method属性配置的
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给BeanPostProcessors一个机会来返回代理来替代真正的实例,解析指定bean是否存在初始化前的短路操作,功能如下:
//1、对BeanDefinition中的属性,做一些前置处理;
// 2、对原有方法的逻辑进行扩展,如果resolveBeforeInstantiation()返回值不为null,则略过了后续bean的创建,AOP正是基于这种原理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//创建bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}

逻辑如下(4条):
①、根据设置的class属性或者根据className来解析Class。
②、对override属性标记及验证。


- 在bean的实例化过程中,如果检测到methodOverrides属性,会动态的为当前bean生成代理并使用对应的拦截器为bean做增强处理。
- 如果当前类中的方法只有一个,那么就设置重载方法的属性为false,这样在后续调用中可以直接找到方法、同时count==0时,对方法的存在性进行验证。
③、应用初始化前的后处理器,解析指定的bean是否存在初始化前的短路操作。




④、创建bean。
7、循环依赖
循环依赖就是多个bean之间互相持有对方。循环依赖=循环引用;循环依赖≠循环调用。循环调用是方法之间的环调用,除非有终结条件,否则无法结束,导致内存溢出。

7.1、循环依赖-构造器循环依赖(spring无法解决)
通过构造器注入的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常。
Spring 容器将每一个正在创建的bean 标识符放在一个“当前创建bean 池”中, bean 标识符在创建过程中将一直保持在这个池中,因此如果在创建bean 过程中发现自己已经在“当前创建bean 池” 里时,将抛出BeanCurrentlylnCreationException 异常表示循环依赖;而对于创建完毕的bean 将从“ 当前创建bean 池”中清除掉。


代码展示:
- 循环依赖的类
package com.chelong.circleReference;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Bean {
public static void main(String[] args) {
try {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-circleReference.xml");
} catch (Exception e) {
Throwable el = e.getCause().getCause().getCause();
el.printStackTrace();
}
}
}
class TestA{
private TestB testB;
public TestA(TestB testB){
this.testB = testB;
}
}
class TestB{
private TestC testC;
public TestB(TestC testC) {
this.testC = testC;
}
}
class TestC{
private TestA testA;
public TestC(TestA testA) {
this.testA = testA;
}
}
- 配置文件spring-circleReference.xml
<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="testA" class="com.chelong.circleReference.TestA" scope="singleton">
<constructor-arg index="0" ref="testB"/>
</bean>
<bean id="testB" class="com.chelong.circleReference.TestB" scope="singleton">
<constructor-arg index="0" ref="testC"/>
</bean>
<bean id="testC" class="com.chelong.circleReference.TestC" scope="singleton">
<constructor-arg index="0" ref="testA"/>
</bean>
</beans>
报错:

①、Spring 容器创建 "testA" bean ,首先去“当前创建bean 池” 查找是否当前bean 正在创建,如果没发现,则继续准备其需要的构造器参数"testB",并将"testA"标识符放到“当前创建bean 池" 。
②、Spring 容器创建 "testB" bean ,首先去“当前创建bean 池” 查找是否当前bean 正在创建,如果没发现,则继续准备其需要的构造器参数"testC",并将"testB"标识符放到“当前创建bean 池" 。
③Spring 容器创建 "testC" bean ,首先去“当前创建bean 池” 查找是否当前bean 正在创建,如果没发现,则继续准备其需要的构造器参数"testA",并将"testC"标识符放到“当前创建bean 池" 。
④到此为止Spring 容器要去创建“testA ” bean ,发现该bean 标识符在“当前创建bean池”中,因为表示循环依赖,抛出BeanCurrentlyInCreationException。
7.2、循环依赖-setter循环依赖(singleton作用域,spring可以解决)
对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使其他bean能引用到该bean。




最后:

代码展示:
- 循环依赖的类
package com.chelong.circleReference;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Bean {
public static void main(String[] args) {
try {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-circleReference.xml");
TestA testA = (TestA) context.getBean("testA");
System.out.println(testA);
} catch (Exception e) {
Throwable el = e.getCause().getCause().getCause();
el.printStackTrace();
}
}
}
class TestA {
private TestB testB;
public void a() {
testB.b();
}
public TestB getTestB() {
return testB;
}
public void setTestB(TestB testB) {
this.testB = testB;
}
}
class TestB {
private TestC testC;
public void b() {
testC.c();
}
public TestC getTestC() {
return testC;
}
public void setTestC(TestC testC) {
this.testC = testC;
}
}
class TestC {
private TestA testA;
public void c() {
testA.a();
}
public TestA getTestA() {
return testA;
}
public void setTestA(TestA testA) {
this.testA = testA;
}
}
- 配置文件spring-circleReference.xml
<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="testA" class="com.chelong.circleReference.TestA" scope="singleton">
<property name="testB" ref="testB"/>
</bean>
<bean id="testB" class="com.chelong.circleReference.TestB" scope="singleton">
<property name="testC" ref="testC"/>
</bean>
<bean id="testC" class="com.chelong.circleReference.TestC" scope="singleton">
<property name="testA" ref="testA"/>
</bean>
</beans>
7.3、循环依赖-setter循环依赖(prototype作用域,spring不能解析)
将7.2中spring-circleReference.xml配置文件修改为scope="prototype",则无法解析该循环依赖。
<bean id="testA" class="com.chelong.circleReference.TestA" scope="prototype">
<property name="testB" ref="testB"/>
</bean>
对于“prototype”作用域bean, Spring 容器无法完成依赖注入,因为Spring 容器不进行缓存“prototype”作用域的bean ,因此无法提前暴露一个创建中的bean 。



浙公网安备 33010602011771号