共计 19811 个字符,预计需要花费 50 分钟才能阅读完成。
概述
后面咱们曾经剖析了 spring 对于 xml 配置文件的解析,将剖析的信息组装成 BeanDefinition,并将其保留注册到相应的 BeanDefinitionRegistry 中。至此,Spring IOC 的初始化工作实现。接下来咱们将对 bean 的加载进行摸索。
BeanFactory
当咱们显示或者隐式地调用 getBean()
时,则会触发加载 bean 阶段。如下:
public class AppTest {
@Test
public void MyTestBeanTest() {BeanFactory bf = new XmlBeanFactory( new ClassPathResource("spring-config.xml"));
MyTestBean myTestBean = (MyTestBean) bf.getBean("myTestBean");
}
}
咱们看到这个办法是在接口 BeanFactory 中定义的,咱们看下 BeanFactory 体系结构,如下图所示:
从上图咱们看到:
(1)BeanFactory 作为一个主接口不继承任何接口,暂且称为一级接口。
(2)有 3 个子接口继承了它,进行性能上的加强。这 3 个子接口称为二级接口。
(3)ConfigurableBeanFactory 能够被称为三级接口,对二级接口 HierarchicalBeanFactory 进行了再次加强,它还继承了另一个外来的接口 SingletonBeanRegistry
(4)ConfigurableListableBeanFactory 是一个更弱小的接口,继承了上述的所有接口,无所不包,称为四级接口。(这 4 级接口是 BeanFactory 的根本接口体系。
(5)AbstractBeanFactory 作为一个抽象类,实现了三级接口 ConfigurableBeanFactory 大部分性能。
(6)AbstractAutowireCapableBeanFactory 同样是抽象类,继承自 AbstractBeanFactory,并额定实现了二级接口 AutowireCapableBeanFactory
(7)DefaultListableBeanFactory 继承自 AbstractAutowireCapableBeanFactory,实现了最弱小的四级接口 ConfigurableListableBeanFactory,并实现了一个外来接口 BeanDefinitionRegistry,它并非抽象类。
(8)最初是最弱小的 XmlBeanFactory,继承自 DefaultListableBeanFactory,重写了一些性能,使本人更弱小。
定义
BeanFactory,以 Factory 结尾,示意它是一个工厂类 (接口), 它负责生产和治理 bean 的一个工厂。在 Spring 中,BeanFactory 是 IOC 容器的外围接口,它的职责包含:实例化、定位、配置应用程序中的对象及建设这些对象间的依赖。BeanFactory 只是个接口,并不是 IOC 容器的具体实现,然而 Spring 容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext 等,其中XmlBeanFactory 就是罕用的一个,该实现将以 XML 形式形容组成利用的对象及对象间的依赖关系。XmlBeanFactory 类将持有此 XML 配置元数据,并用它来构建一个齐全可配置的零碎或利用。
BeanFactory 是 Spring IOC 容器的鼻祖,是 IOC 容器的根底接口,所有的容器都是从它这里继承实现而来。可见其位置。BeanFactory 提供了最根本的 IOC 容器的性能,即所有的容器至多须要实现的规范。
XmlBeanFactory,只是提供了最根本的 IOC 容器的性能。而且 XMLBeanFactory, 继承自 DefaultListableBeanFactory。DefaultListableBeanFactory 理论蕴含了根本 IOC 容器所具备的所有重要性能,是一个残缺的 IOC 容器。
ApplicationContext 蕴含 BeanFactory 的所有性能,通常倡议比 BeanFactory 优先。
BeanFactory 体系结构是典型的工厂办法模式,即什么样的工厂生产什么样的产品。BeanFactory 是最根本的形象工厂,而其余的 IOC 容器只不过是具体的工厂,对应着各自的 Bean 定义方法。但同时,其余容器也针对具体场景不同,进行了裁减,提供具体的服务。如下:
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml"});
BeanFactory factory = (BeanFactory) context;
根本就是这些了,接着应用 getBean(String beanName)办法就能够获得 bean 的实例;BeanFactory 提供的办法及其简略,仅提供了六种办法供客户调用:
- boolean containsBean(String beanName) 判断工厂中是否蕴含给定名称的 bean 定义,若有则返回 true
- Object getBean(String) 返回给定名称注册的 bean 实例。依据 bean 的配置状况,如果是 singleton 模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定 bean, 该办法可能会抛出异样
- Object getBean(String, Class) 返回以给定名称注册的 bean 实例,并转换为给定 class 类型
- Class getType(String name) 返回给定名称的 bean 的 Class, 如果没有找到指定的 bean 实例,则排除 NoSuchBeanDefinitionException 异样
- boolean isSingleton(String) 判断给定名称的 bean 定义是否为单例模式
- String[] getAliases(String name) 返回给定 bean 名称的所有别名
package org.springframework.beans.factory;
import org.springframework.beans.BeansException;
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
FactoryBean
个别状况下,Spring 通过反射机制利 用 <bean>
的 class 属性指定实现类实例化 Bean,在某些状况下,实例化 Bean 过程比较复杂,如果依照传统的形式,则须要在 <bean>
中提供大量的配置信息。配置形式的灵活性是受限的,这时采纳编码的形式可能会失去一个简略的计划。Spring 为此提供了一个 org.springframework.bean.factory.FactoryBean 的工厂类接口,用户能够通过实现该接口定制实例化 Bean 的逻辑。FactoryBean 接口对于 Spring 框架来说占用重要的位置,Spring 本身就提供了 70 多个 FactoryBean 的实现。它们暗藏了实例化一些简单 Bean 的细节,给下层利用带来了便当。从 Spring3.0 开始,FactoryBean 开始反对泛型,即接口申明改为 FactoryBean<T>
的模式。
以 Bean 结尾,示意它是一个 Bean,不同于一般 Bean 的是:它是实现了 FactoryBean<T> 接口的 Bean,依据该 Bean 的 ID 从 BeanFactory 中获取的实际上是 FactoryBean 的 getObject()返回的对象,而不是 FactoryBean 自身,如果要获取 FactoryBean 对象,请在 id 后面加一个 & 符号来获取。
package org.springframework.beans.factory;
public interface FactoryBean<T> {T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();}
在该接口中还定义了以下 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 的 <bean>
时,Car 的每个属性别离对应一个 <property>
元素标签。
public class Car {
private int maxSpeed ;
private String brand ;
private double price ;
//get//set 办法
}
如果用 FactoryBean 的形式实现就灵便点,下例通过逗号宰割符的形式一次性的为 Car 的所有属性指定配置值:
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.setBrand(infos[0]);
car.setMaxSpeed(Integer.valueOf(infos[1]));
car.setPrice(Double.valueOf(infos[2]));
return car;
}
public Class<Car> getObjectType(){return Car.class ;}
public boolean isSingleton(){return false ;}
public String getCarInfo(){return this.carInfo;}
// 承受逗号宰割符设置属性信息
public void setCarInfo (String carInfo){this.carInfo = carInfo;}
}
有了这个 CarFactoryBean 后,就能够在配置文件中应用上面这种自定义的配置形式配置 CarBean 了:
<bean d="car"class="com.dabin.spring.CarFactoryBean" P:carInfo="大奔,600,1000000"/>
当调用 getBean(“car”)时,Spring 通过反射机制发现 CarFactoryBean 实现了 FactoryBean 的接口,这时 Spring 容器就调用接口办法 CarFactoryBean#getObject()办法返回。如果心愿获取 CarFactoryBean 的实例,则须要在应用 getBean(beanName)办法时在 beanName 前显示的加上 ”&” 前缀:如 getBean(“&car”);
获取 bean
接下来咱们回到加载 bean 的阶段,当咱们显示或者隐式地调用 getBean()
时,则会触发加载 bean 阶段。如下:
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);
}
外部调用 doGetBean()
办法,这个办法的代码比拟长,各位急躁看下:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 获取 beanName,这里是一个转换动作,将 name 转换为 beanName
final String beanName = transformedBeanName(name);
Object bean;
/*
* 查看缓存中的实例工程是否存在对应的实例
* 为何要优先应用这段代码呢?* 因为在创立单例 bean 的时候会存在依赖注入的状况,而在创立依赖的时候为了防止循环依赖
*spring 创立 bean 的准则是在不等 bean 创立完就会将创立 bean 的 objectFactory 提前曝光,行将其退出到缓存中,一旦下个 bean 创立时依赖上个 bean 则间接应用 objectFactory
* 间接从缓存中或 singletonFactories 中获取 objectFactory
* 就算没有循环依赖,只是单纯的依赖注入,如 B 依赖 A,如果 A 曾经初始化实现,B 进行初始化时,须要递归调用 getBean 获取 A,这是 A 曾经在缓存里了,间接能够从这里取到
*/
// Eagerly check singleton cache for manually registered singletons.
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 + "'");
}
}
// 返回对应的实例,有些时候并不是间接返回实例,而是返回某些办法返回的实例
// 这里波及到咱们下面讲的 FactoryBean,如果此 Bean 是 FactoryBean 的实现类,如果 name 前缀为 "&", 则间接返回此实现类的 bean, 如果没有前缀 "&",则须要调用此实现类的 getObject 办法,返回 getObject 外面真是的返回对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 只有在单例的状况下才会解决循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
}
// 尝试从 parentBeanFactory 中查找 bean
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);
}
}
// 如果不是仅仅做类型查看,则这里须要创立 bean,并做记录
if (!typeCheckOnly) {markBeanAsCreated(beanName);
}
try {
// 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,同时如果存在父 bean 的话则合并父 bean 的相干属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 如果存在依赖则须要递归实例化依赖的 bean
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);
}
}
}
// 单例模式
// 实例化依赖的 bean 后对 bean 自身进行实例化
if (mbd.isSingleton()) {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()) {
// 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);
}
// 从指定的 scope 下创立 bean
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.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;
}
代码是相当长,解决逻辑也是相当简单,上面将其进行拆分解说。
获取 beanName
final String beanName = transformedBeanName(name);
这里传递的是 name,不肯定就是 beanName,可能是 aliasName,也有可能是 FactoryBean(带“&”前缀),所以这里须要调用 transformedBeanName()
办法对 name 进行一番转换,次要如下:
protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// 去除 FactoryBean 的修饰符
public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");
String beanName = name;
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
// 转换 aliasName
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {canonicalName = resolvedName;}
}
while (resolvedName != null);
return canonicalName;
}
次要处理过程包含两步:
- 去除 FactoryBean 的修饰符。如果 name 以“&”为前缀,那么会去掉该“&”,例如,
name = "&studentService"
,则会是name = "studentService"
。 - 取指定的 alias 所示意的最终 beanName。次要是一个循环获取 beanName 的过程,例如别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。
缓存中获取单例 bean
单例在 Spring 的同一个容器内只会被创立一次,后续再获取 bean 间接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,而后再次尝试从 singletonFactorry 加载因为在创立单例 bean 的时候会存在依赖注入的状况,而在创立依赖的时候为了防止循环依赖,Spring 创立 bean 的准则不等 bean 创立实现就会创立 bean 的 ObjectFactory 提前曝光退出到缓存中,一旦下一个 bean 创立时须要依赖上个 bean,则间接应用 ObjectFactory;就算没有循环依赖,只是单纯的依赖注入,如 B 依赖 A,如果 A 曾经初始化实现,B 进行初始化时,须要递归调用 getBean 获取 A,这是 A 曾经在缓存里了,间接能够从这里取到。接下来咱们看下获取单例 bean 的办法 getSingleton(beanName),进入办法体:
@Override
@Nullable
public Object getSingleton(String beanName) {
// 参数 true 是容许晚期依赖
return getSingleton(beanName, true);
}
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 查看缓存中是否存在实例, 这里就是下面说的单纯的依赖注入,如 B 依赖 A,如果 A 曾经初始化实现,B 进行初始化时,须要递归调用 getBean 获取 A,这是 A 曾经在缓存里了,间接能够从这里取到
Object singletonObject = this.singletonObjects.get(beanName);
// 如果缓存为空且单例 bean 正在创立中,则锁定全局变量,为什么要判断 bean 在创立中呢?这里就是能够判断是否循环依赖了。// A 依赖 B,B 也依赖 A,A 实例化的时候,发现依赖 B,则递归去实例化 B,B 发现依赖 A,则递归实例化 A,此时会走到原点 A 的实例化,第一次 A 的实例化还没实现,只不过把实例化的对象退出到缓存中,然而状态还是正在创立中,由此回到原点发现 A 正在创立中,由此能够判断是循环依赖了
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {
// 如果此 bean 正在加载,则不解决
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 当某些办法须要提前初始化的时候会间接调用 addSingletonFactory 把对应的 ObjectFactory 初始化策略存储在 singletonFactory 中
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 应用事后设定的 getObject 办法
singletonObject = singletonFactory.getObject();
记录在缓存中,留神 earlySingletonObjects 和 singletonFactories 是互斥的
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
接下来咱们依据源码再来梳理下这个办法,这样更易于了解,这个办法先尝试从 singletonObjects 外面获取实例,如果如果获取不到再从 earlySingletonObjects 外面获取,如果还获取不到,再尝试从 singletonFactories 外面获取 beanName 对应的 ObjectFactory,而后再调用这个 ObjectFactory 的 getObject 办法创立 bean, 并放到 earlySingletonObjects 外面去,并且从 singletonFactoryes 外面 remove 调这个 ObjectFactory,而对于后续所有的内存操作都只为了循环依赖检测时候应用,即 allowEarlyReference 为 true 的时候才会应用。
这里波及到很多个存储 bean 的不同 map,简略解释下:
1.singletonObjects: 用于保留 BeanName 和创立 bean 实例之间的关系,beanName–>bean Instance
2.singletonFactories: 用于保留 BeanName 和创立 bean 的工厂之间的关系,banName–>ObjectFactory
3.earlySingletonObjects: 也是保留 BeanName 和创立 bean 实例之间的关系,与 singletonObjects 的不同之处在于,当一个单例 bean 被放到这外面后,那么当 bean 还在创立过程中,就能够通过 getBean 办法获取到了,其目标是用来检测循环援用。
4.registeredSingletons:用来保留以后所有已注册的 bean.
从 bean 的实例中获取对象
获取到 bean 当前就要获取实例对象了,这里用到的是 getObjectForBeanInstance 办法。getObjectForBeanInstance 是个频繁应用的办法,无论是从缓存中取得 bean 还是依据不同的 scope 策略加载 bean. 总之,咱们失去 bean 的实例后,要做的第一步就是调用这个办法来检测一下正确性,其实就是检测取得 Bean 是不是 FactoryBean 类型的 bean, 如果是,那么须要调用该 bean 对应的 FactoryBean 实例中的 getObject()作为返回值。接下来咱们看下此办法的源码:
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果指定的 name 是工厂相干的(以 & 结尾的)if (BeanFactoryUtils.isFactoryDereference(name)) {
// 如果是 NullBean 则间接返回此 bean
if (beanInstance instanceof NullBean) {return beanInstance;}
// 如果不是 FactoryBean 类型,则验证不通过抛出异样
if (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), 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 不是 FactoryBean 类型,则阐明是一般的 Bean,可间接返回
// 如果获取的 beanInstance 是 FactoryBean 类型, 然而是以(以 & 结尾的),也间接返回,此时返回的是 FactoryBean 的实例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}
Object object = null;
if (mbd == null) {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.
if (mbd == null && containsBeanDefinition(beanName)) {mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 到了这里阐明获取的 beanInstance 是 FactoryBean 类型, 但没有以 "&" 结尾,此时就要返回 factory 外部 getObject 外面的对象了
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
接着咱们来看看真正的外围性能 getObjectFromFactoryBean(factory, beanName, !synthetic)办法中实现的,持续跟进代码:
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 为单例模式且缓存中存在
if (factory.isSingleton() && containsSingleton(beanName)) {synchronized (getSingletonMutex()) {
// 从缓存中获取指定的 factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 为空,则从 FactoryBean 中获取对象
object = doGetObjectFromFactoryBean(factory, beanName);
// 从缓存中获取
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {object = alreadyThere;}
else {
// 须要后续解决
if (shouldPostProcess) {
// 若该 bean 处于创立中,则返回非解决对象,而不是存储它
if (isSingletonCurrentlyInCreation(beanName)) {return object;}
// 前置解决
beforeSingletonCreation(beanName);
try {
// 对从 FactoryBean 获取的对象进行后处理
// 生成的对象将裸露给 bean 援用
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;
}
}
该办法应该就是创立 bean 实例对象中的外围办法之一了。这里咱们关注三个办法:beforeSingletonCreation()
、afterSingletonCreation()
、postProcessObjectFromFactoryBean()
。可能有小伙伴感觉后面两个办法不是很重要,LZ 能够必定通知你,这两办法是十分重要的操作,因为他们记录着 bean 的加载状态,是检测以后 bean 是否处于创立中的要害之处,对解决 bean 循环依赖起着关键作用。before 办法用于标记以后 bean 处于创立中,after 则是移除。其实在这篇博客刚刚开始就曾经提到了 isSingletonCurrentlyInCreation()
是用于检测以后 bean 是否处于创立之中,如下:
public boolean isSingletonCurrentlyInCreation(String beanName) {return this.singletonsCurrentlyInCreation.contains(beanName);
}
是依据 singletonsCurrentlyInCreation 汇合中是否蕴含了 beanName,汇合的元素则肯定是在 beforeSingletonCreation()
中增加的,如下:
protected void beforeSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
}
}
afterSingletonCreation()
为移除,则肯定就是对 singletonsCurrentlyInCreation 汇合 remove 了,如下:
protected void afterSingletonCreation(String beanName) {if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {throw new IllegalStateException("Singleton'" + beanName + "'isn't currently in creation");
}
}
咱们再来看看真正的外围办法 doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final 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 {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 的调用办法,如果 bean 申明为 FactoryBean 类型,则当提取 bean 时候提取的不是 FactoryBean,而是 FactoryBean 中对应的 getObject 办法返回的 bean, 而 doGetObjectFromFactroyBean 真是实现这个性能。
而调用完 doGetObjectFromFactoryBean 办法后,并没有间接返回,getObjectFromFactoryBean 办法中还调用了 object = postProcessObjectFromFactoryBean(object, beanName); 办法,在子类 AbstractAutowireCapableBeanFactory,有这个办法的实现:
@Override
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {return applyBeanPostProcessorsAfterInitialization(object, beanName);
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {return result;}
result = current;
}
return result;
}
对于后处理器的应用,咱们目前还没接触,后续会有大量篇幅介绍,这里咱们只须要理解在 Spring 获取 bean 的规定中有这样一条:尽可能保障所有 bean 初始化后都会调用注册的 BeanPostProcessor 的 postProcessAfterInitialization 办法进行解决,在理论开发过程中大能够针对此个性设计本人的业务解决。