Spring源码分析 (六)Bean的加载过程
- 官网:Home
- 参考书籍:Spring源码深度解析-郝佳编著-微信读书
经过前面的分析我们已经结束了对XML配置文件的解析,接下来我们来看对Bean的加载
package org.springframework.shu;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
/**
* @description: 测试Bean
* @author: shu
* @createDate: 2023/4/3 14:56
* @version: 1.0
*/
public class AppTest {
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory( new ClassPathResource("spring-config.xml"));
MyTestBean myTestBean = (MyTestBean) bf.getBean("myTestBean");
System.out.println(myTestBean.getName());
}
}
下面我们仔细来看看呗 AbstractBeanFactory
// 调用重载方法
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean
typeCheckOnly) throws BeansException {
//提取对应的beanName
final String beanName = transformedBeanName(name);
Object bean;
/*
* 检查缓存中或者实例工厂中是否有对应的实例
* 为什么首先会使用这段代码呢,
* 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
* Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
* 也就是将ObjectFactory加入到缓存中,一旦下个bean创建时候需要依赖上个bean则直接使用
ObjectFactory
*/
//直接尝试从缓存获取或者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的情况并不是直接返回实例本身而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {
//只有在单例情况才会尝试解决循环依赖,原型模式情况下,如果存在
//A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为
//对于B的创建再次返回创建A,造成循环依赖,也就是下面的情况
//isPrototypeCurrentlyInCreation(beanName)为true
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果 beanDefinitionMap 中也就是在所有已经加载的类中不包括 beanName 则尝试从
parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
//递归到BeanFactory中寻找
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//如果不是仅仅做类型检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
//将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指
定BeanName是子Bean的话同时会合并父类的相关属性
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
//若存在依赖则需要递归实例化依赖的bean
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
//缓存依赖调用
registerDependentBean(dependsOnBean, beanName);
}
}
//实例化依赖的bean后便可以实例化mbd本身了
//singleton模式的创建
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}else if (mbd.isPrototype()) {
//prototype模式的创建(new)
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();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '"
+ scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
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);
}
}
}
//检查需要的类型是否符合bean的实际类型
if (requiredType != null && bean != null && !requiredType.isAssignableFrom
(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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
或许很多人不理解转换对应beanName是什么意思,传入的参数name不就是beanName吗?其实不是,这里传入的参数可能是别名,也可能是FactoryBean,所以需要进行一系列的解析,这些解析内容包括如下内容。 去除FactoryBean的修饰符,也就是如果name="&aa",那么会首先去除&而使name="aa"。 取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B;若别名A指向别名B,别名B又指向名称为C的bean则返回C。
- 尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试加载,首先尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory
- bean的实例化
如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里有必要强调一下,缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。举个例子,假如我们需要对工厂bean进行处理,那么这里得到的其实是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的factory-method方法中返回的bean,而getObjectForBeanInstance就是完成这个工作的,后续会详细讲解。
- 原型模式的依赖检查
只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况:isPrototypeCurrentlyInCreation(beanName)判断true。
- 检测parentBeanFactory
从代码上看,如果缓存没有数据的话直接转到父类工厂上去加载了,这是为什么呢?可能读者忽略了一个很重要的判断条件:parentBeanFactory != null &&!containsBean Definition (beanName),parentBeanFactory != null。parentBeanFactory如果为空,则其他一切都是浮云,这个没什么说的,但是!containsBeanDefinition(beanName)就比较重要了,它是在检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下了,然后再去递归的调用getBean方法。
- 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
因为从XML配置文件中读取到的Bean信息是存储在GernericBeanDefinition中的,但是所有的Bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性。
- 寻找依赖
因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖
- 针对不同的scope进行bean的创建
在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略。
- 类型转换
程序到这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是为空的,但是可能会存在这样的情况,返回的bean其实是个String,但是requiredType却传入Integer类型,那么这时候本步骤就会起作用了,它的功能是将返回的bean转换为requiredType所指定的类型。当然,String转换为Integer是最简单的一种转换,在Spring中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求。 这就是上面的代码的一个基本流程,看起来代码不多,其实代码十分复杂,我们接着往下看,根据上面的流程我们一一拆解
1.1 转换对应beanName
// 提取对应的beanName
String beanName = transformedBeanName(name);
这里我们也许会有疑问,我们一般不就传入的就是我们命名的beanName吗?为啥还需要转换一下? 我们可以从源码中可以看到,它对传入的名称进行了一下判断 BeanFactoryUtils
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// String FACTORY_BEAN_PREFIX = "&";
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// 如果是String FACTORY_BEAN_PREFIX = "&";
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
那什么时候会在beanName前显示的加上"&" 前缀?简单来说就是继承了FactoryBean,下面我们来看代码实战
说明
package com.shu.model;
/**
* @description:
* @author: shu
* @createDate: 2023/8/29 9:47
* @version: 1.0
*/
public class Car {
private int maxSpeed;
private String brand;
private double price;
public int getMaxSpeed() {
return this.maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return this.brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return this.price;
}
public void setPrice(double price) {
this.price = price;
}
}
package com.shu.test;
import com.shu.model.Car;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
import org.springframework.beans.factory.ListableBeanFactory;
/**
* @description: FactoryBean接口的实现类,用于测试FactoryBean的使用
* @author: shu
* @createDate: 2023/8/29 9:47
* @version: 1.0
*/
public class CarFactoryBean implements FactoryBean<Car>{
private String carInfo ;
public Car getObject () throws Exception {
Car car = new Car () ;
car.setBrand ( "红旗CA72" ) ;
car.setMaxSpeed ( 200 ) ;
car.setPrice ( 1000000 ) ;
return car;
}
public Class<Car> getObjectType () {
return Car. class ;
}
public boolean isSingleton () {
return false ;
}
public String getCarInfo () {
return this . carInfo ;
}
}
而我们的配置文件中
<bean name="car" class="com.shu.test.CarFactoryBean" />
/**
* 测试FactoryBean
*/
@Test
public void factoryBeanTest() {
BeanFactory bf = new XmlBeanFactory( new ClassPathResource("applicationContext.xml"));
Object car = bf.getBean("&car");
System.out.println(car);
}
当调用getBean("car")时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean#getObject()方法返回。如果希望获取CarFactoryBean的实例,则需要在使用getBean(beanName)方法时在beanName前显示的加上"&" 前缀,请注意有&符号和没有&符号获取的对象不一样 最后一步,转换别名,我们的bean实例可能会有多个别名
// 转换 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 以 “&” 为前缀,那么会去掉该 “&”
- 指定的 alias 所表示的最终 beanName。主要是一个循环获取 beanName 的过程,例如别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。
1.2 尝试从缓存中加载单例
- 单例在Spring的同一个容器内只会被创建一次,后续再获取bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试尝试从singletonFactories中加载。
- 因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖, Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上个bean,则直接使用ObjectFactory。
AbstractBeanFactory
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 + "'");
}
}
// //返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
首先我们理清关系:
- singletonObjects:用于保存BeanName和创建bean实例之间的关系,bean name --> bean instance。
- singletonFactories:用于保存BeanName和创建bean的工厂之间的关系,bean name ->ObjectFactory。
- earlySingletonObjects:也是保存BeanName和创建bean实例之间的关系,与singletonObjects的不同之处在于,当一个单例bean被放到这里面后,那么当bean还在创建过程中,就可以通过getBean方法获取到了,其目的是用来检测循环引用。
- registeredSingletons:用来保存当前所有已注册的bean。
我们可以看到关键的方法在于getSingleton,下面我们仔细来看看
public Object getSingleton(String beanName) {
//参数true设置标识允许早期依赖
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//如果为空,则锁定全局变量并进行处理
synchronized (this.singletonObjects) {
//如果此bean正在加载则不处理
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//当某些方法需要提前初始化的时候则会调用 addSingletonFactory 方法将对应
的ObjectFactory初始化策略存储在singletonFactories
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 != NULL_OBJECT ? singletonObject : null);
}
我们梳理一下过程:
- 这个方法首先尝试从singletonObjects里面获取实例
- 如果获取不到再从earlySingleton Objects里面获取
- 如果还获取不到,再尝试从singletonFactories里面获取beanName对应的ObjectFactory
- 然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingleton Objects里面去
- 并且从singletonFacotories里面remove掉这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是在allowEarlyReference为true的情况下才会使用。
1.3 bean的实例化
如果我们其他地方使用了该Bean,然后我们再次获取该Bean就会发现它尝试从缓存中加载 接着上面我们如果从缓存中加载到了单例对象,下面就是bean的实例化,从上面的代码来看我们无论从singletonObjects还是ObjectFactory中加载的单例对象都是原始对象,所以要进行bean的实例化
请注意下面的逻辑是正对实现了FactoryBean接口的bean,且缓存中存在,也就是说第二次使用
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
- getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获得bean还是根据不同的scope策略加载bean。
- 我们得到bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
//如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof
FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.
getClass());
}
//现在我们有了个bean的实例,这个实例可能会是正常的bean或者是FactoryBean
//如果是 FactoryBean 我们使用它创建实例,但是如果用户想要直接获取工厂实例而不是工厂的
getObject方法对应的实例那么传入的name应该加入前缀&
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils. IsFactory
Dereference(name)) {
return beanInstance;
}
//加载FactoryBean
Object object = null;
if (mbd == null) {
//尝试从缓存中加载bean
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//到这里已经明确知道beanInstance一定是FactoryBean类型
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
//containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测
是否定义beanName
if (mbd == null && containsBeanDefinition(beanName)) {
//将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,
如果指定BeanName是子Bean的话同时会合并父类的相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
//是否是用户定义的而不是应用程序本身定义的
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
情况一:正常的bean 情况二:FactoryBean 流程梳理:
- 对FactoryBean正确性的验证
- 对非FactoryBean不做任何处理
- 尝试从缓存中加载Bean,如果有直接换行,存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition后面会详细解释
- 缓存中有的话,交给getObjectFromFactoryBean方法进行处理,去执行FactoryBean接口实现类的getObject()也就是CarFactoryBean中的getObject方法
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 判断是否是单例模式 && singletonObjects 尚未缓存该bean (containsSingleton调用的是 singletonObjects )
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 尝试从 factoryBeanObjectCache 缓存中获取
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 在这个方法中进行解析。调用 FactoryBean 的 getObject 方法
object = doGetObjectFromFactoryBean(factory, beanName);
// 因为是单例模式,所以要保证变量的全局唯一。所以这里如果缓存中已经创建好了bean则替换为已经创建好的bean
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
// 如果允许调用bean的后置处理器。因为这里是直接将bean创建返回了,如果要调用后置方法则只能在这里调用。
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 将beanName 添加到 singletonsCurrentlyInCreation 中缓存,表示当前bean正在创建中
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 {
// 将beanName 从 singletonsCurrentlyInCreation 中移除,表示当前bean已经创建结束
afterSingletonCreation(beanName);
}
}
// return this.singletonObjects.containsKey(beanName); 如果 singletonObjects缓存中存在当前beanName,则将其缓存到 factoryBeanObjectCache 中。
if (containsSingleton(beanName)) {
// 这里保存的是 beanName : FactoryBean
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
// FactoryBean 非单例直接调用 getObject 方法
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 如果允许调用后置方法,则调用postProcessObjectFromFactoryBean 方法
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
下面我们来看看关键的核心方法doGetObjectFromFactoryBean,也就是上面CarFactoryBean实现的核心逻辑
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
// 权限访问
if (System.getSecurityManager() != null) {
AccessControlContext acc = this.getAccessControlContext();
try {
object = AccessController.doPrivileged(factory::getObject, acc);
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
// 自己的实现类去加载对象
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException var7) {
throw new BeanCurrentlyInCreationException(beanName, var7.toString());
} catch (Throwable var8) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
}
if (object == null) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}
我们简单梳理一下上面的代码逻辑:我们的目的从工厂中加载对象,让后在调用后置处理器,在实际开发过程中可以针对进行自己的业务逻辑设计 我们来总结一下:
- 我们尝试从缓存中加载实例对象,一般第一次使用肯定没有的,那就第二次使用的时候
- 由于我们从缓存中尝试加载的对象是原始对象,因此我们需要实例化它
- 但是实例化的时候分为正常情况的Bean与实现了FactoryBean接口的Bean
- 正常情况下的Bean直接返回,复杂情况的Bean需要调用我们自己实现了FactoryBean接口的getObject方法来实例它
1.4 原型模式的依赖检查
之前我们讲解了从缓存中获取单例的过程,上面的逻辑是正对缓存中不为空的情况,下面我们来看那可能缓存如果为空咋办,那就是第一次进行初始化呗,我们接着往下看? 只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况:isPrototypeCurrentlyInCreation(beanName)判断true。
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
总结一下:
- 对于单例模式 Spring 在创建 bean 的时候并不是等 bean 完全创建完成后才会将 bean 添加至缓存中,而是不等 bean 创建完成就会将创建 bean 的 ObjectFactory 提早加入到缓存中,这样一旦下一个 bean 创建的时候需要依赖 bean 时则直接使用 ObjectFactroy。
- 但是原型模式我们知道是没法使用缓存的,所以 Spring 对原型模式的循环依赖处理策略则是不处理
1.5 检测parentBeanFactory
若 containsBeanDefinition 中不存在 beanName 相对应的 BeanDefinition,则从 parentBeanFactory 中获取。 AbstractBeanFactory
//AbstractBeanFactory.java
// 获取父容器
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查父容器
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 获取原始 beanName
String nameToLookup = originalBeanName(name);
// 如果,父类容器为 AbstractBeanFactory ,直接递归查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
// 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象
} else if (args != null) {
return (T)parentBeanFactory.getBean(nameToLookup, args);
// 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象
} else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
// 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象
} else {
return (T)parentBeanFactory.getBean(nameToLookup);
}
}
获取父容器 AbstractBeanFactory
//AbstractBeanFactory.java
private BeanFactory parentBeanFactory;
@Override
public BeanFactory getParentBeanFactory() {
return this.parentBeanFactory;
}
若父容器不为空,并且 beanDefinitionMap 中没有找到对应的 BeanDefinition 对象 DefaultListableBeanFactory
//DefaultListableBeanFactory.java
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
@Override
public boolean containsBeanDefinition(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return this.beanDefinitionMap.containsKey(beanName);
}
获取原始 beanName AbstractBeanFactory
//AbstractBeanFactory.java
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name); // <x>
if (name.startsWith(FACTORY_BEAN_PREFIX)) { // <y>
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}
- x 处,AbstractBeanFactory#transformedBeanName(String name) 方法,是对 name 进行转换,获取真正的 beanName。参考前面转换对应的Bean
- y 处,如果 name 是以 "&" 开头的,则加上 "&" ,因为在AbstractBeanFactory#transformedBeanName(String name) 方法中把 "&" 去掉,这边需要补上
委托父容器加载 Bean 的逻辑 AbstractBeanFactory
// 如果,父类容器为 AbstractBeanFactory ,直接递归查找
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
// 用明确的 args 从 parentBeanFactory 中,获取 Bean 对象
} else if (args != null) {
return (T)parentBeanFactory.getBean(nameToLookup, args);
// 用明确的 requiredType 从 parentBeanFactory 中,获取 Bean 对象
} else if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
// 直接使用 nameToLookup 从 parentBeanFactory 获取 Bean 对象
} else {
return (T)parentBeanFactory.getBean(nameToLookup);
}
1.6 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
参考博客:Spring中BeanDefinition的合并getMergedLocalBeanDefinition 在GenericBeanDefinition,ChildBeanDefinition中有一个parentName属性,表示该BeanDefinition的父BeanDefinition,如果该bean在定义中设置了parentName,那么在实例化之前会进行这两个BeanDefinition的合并。 获取 RootBeanDefinition AbstractBeanFactory
//AbstractBeanFactory.java
// 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);
接着获取RootBeanDefinition对象
//返回一个合并的 RootBeanDefinition,如果该bean定义是一个子bean定义,则遍历父bean定义
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
//先从mergedBeanDefinitions容器中取
//如果有,表示该bean定义已经合并过了,则就直接返回;如果没有,则进行合并
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
// // 如果返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
- 如果 mergedBeanDefinitions 缓存中存在对应的 RootBeanDefinition 对象,则直接返回。
- 否则调用AbstractBeanFactory#getMergedBeanDefinition(String beanName, BeanDefinition bd)获取 RootBeanDefinition 对象
- 通过 AbstractBeanFactory#getBeanDefinition(String beanName) 获取 BeanDefinition 对象,如果没有找到就抛出 NoSuchBeanDefinitionException 异常。
/*
* 如果该bean定义是子bean定义,则通过与父级合并返回给定顶级 bean 的 RootBeanDefinition
* @param beanName bean定义的名称
* @param bd 原始的bean定义(Root/ChildBeanDefinition)
* @return 给定bean的(可能合并的)RootBeanDefinition
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
throws BeanDefinitionStoreException {
return getMergedBeanDefinition(beanName, bd, null);
}
/**
* 返回一个合并的RootBeanDefinition,如果该bean定义是一个子bean定义,则合并父bean定义
* @param bean定义的名称
* @param bd 原始的bean定义(Root/ChildBeanDefinition)
* @param containingBd 如果是内部bean,则包含bean定义,如果是顶级 bean,则为null
* @return 给定bean的(可能合并的)RootBeanDefinition
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null) {
//如果该bean定义没有parent,则不进行合并,返回包装后的RootBeanDefinition
if (bd.getParentName() == null) {
//如果该bean定义是RootBeanDefinition,则直接克隆一份BeanDefinition
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
//如果不是RootBeanDefinition,则包装为RootBeanDefinition
else {
mbd = new RootBeanDefinition(bd);
}
}
//如果该bean定义有parent
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
String parentBeanName = transformedBeanName(bd.getParentName());
//如果parentName不是当前的beanName,则获取父bean合并后的bean定义
if (!beanName.equals(parentBeanName)) {
//递归调用进行父bean定义的合并
pbd = getMergedBeanDefinition(parentBeanName);
}
else {
BeanFactory parent = getParentBeanFactory();
if (parent instanceof ConfigurableBeanFactory) {
pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
}
else {
throw new NoSuchBeanDefinitionException(parentBeanName,
"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
"': cannot be resolved without an AbstractBeanFactory parent");
}
}
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
}
// Deep copy with overridden values.
mbd = new RootBeanDefinition(pbd);
//进行覆盖,用子bean定义中的属性,方法覆盖父bean定义中的属性,方法
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
}
// A bean contained in a non-singleton bean cannot be a singleton itself.
// Let's correct this on the fly here, since this might be the result of
// parent-child merging for the outer bean, in which case the original inner bean
// definition will not have inherited the merged outer bean's singleton status.
if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
mbd.setScope(containingBd.getScope());
}
//将合并后的bean定义放入到缓存中
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
return mbd;
}
}
/**
* 返回给定bean名称合并后的BeanDefinition,如有必要,将子bean定义与其父 bean 合并。
* <p>这个getMergedBeanDefinition也考虑了祖先中的 bean 定义。
* @param name the name of the bean to retrieve the merged definition for
* (may be an alias)
* @return a (potentially merged) RootBeanDefinition for the given bean
* @throws NoSuchBeanDefinitionException if there is no bean with the given name
* @throws BeanDefinitionStoreException in case of an invalid bean definition
*/
@Override
public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
String beanName = transformedBeanName(name);
// Efficiently check whether bean definition exists in this factory.
if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
}
//在本地解析合并的 bean 定义
return getMergedLocalBeanDefinition(beanName);
}
AbstractBeanDefinition中对bean定义的覆盖
/**
* Override settings in this bean definition (presumably a copied parent
* from a parent-child inheritance relationship) from the given bean
* definition (presumably the child).
* <ul>
* <li>Will override beanClass if specified in the given bean definition.
* <li>Will always take {@code abstract}, {@code scope},
* {@code lazyInit}, {@code autowireMode}, {@code dependencyCheck},
* and {@code dependsOn} from the given bean definition.
* <li>Will add {@code constructorArgumentValues}, {@code propertyValues},
* {@code methodOverrides} from the given bean definition to existing ones.
* <li>Will override {@code factoryBeanName}, {@code factoryMethodName},
* {@code initMethodName}, and {@code destroyMethodName} if specified
* in the given bean definition.
* </ul>
*/
public void overrideFrom(BeanDefinition other) {
//如有直接覆盖BeanClassName
if (StringUtils.hasLength(other.getBeanClassName())) {
setBeanClassName(other.getBeanClassName());
}
//如有作用域直接覆盖作用域
if (StringUtils.hasLength(other.getScope())) {
setScope(other.getScope());
}
//覆盖是否抽象
setAbstract(other.isAbstract());
//覆盖是否懒加载
setLazyInit(other.isLazyInit());
//覆盖工厂名
if (StringUtils.hasLength(other.getFactoryBeanName())) {
setFactoryBeanName(other.getFactoryBeanName());
}
//覆盖工厂方法名
if (StringUtils.hasLength(other.getFactoryMethodName())) {
setFactoryMethodName(other.getFactoryMethodName());
}
setRole(other.getRole());
setSource(other.getSource());
//拷贝属性
copyAttributesFrom(other);
if (other instanceof AbstractBeanDefinition) {
AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
if (otherAbd.hasBeanClass()) {
setBeanClass(otherAbd.getBeanClass());
}
if (otherAbd.hasConstructorArgumentValues()) {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
}
if (otherAbd.hasPropertyValues()) {
getPropertyValues().addPropertyValues(other.getPropertyValues());
}
if (otherAbd.hasMethodOverrides()) {
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
}
setAutowireMode(otherAbd.getAutowireMode());
setDependencyCheck(otherAbd.getDependencyCheck());
setDependsOn(otherAbd.getDependsOn());
setAutowireCandidate(otherAbd.isAutowireCandidate());
setPrimary(otherAbd.isPrimary());
copyQualifiersFrom(otherAbd);
setInstanceSupplier(otherAbd.getInstanceSupplier());
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
if (otherAbd.getInitMethodName() != null) {
setInitMethodName(otherAbd.getInitMethodName());
setEnforceInitMethod(otherAbd.isEnforceInitMethod());
}
if (otherAbd.getDestroyMethodName() != null) {
setDestroyMethodName(otherAbd.getDestroyMethodName());
setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
}
setSynthetic(otherAbd.isSynthetic());
setResource(otherAbd.getResource());
}
else {
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
getPropertyValues().addPropertyValues(other.getPropertyValues());
setResourceDescription(other.getResourceDescription());
}
}
protected void copyAttributesFrom(AttributeAccessor source) {
Assert.notNull(source, "Source must not be null");
String[] attributeNames = source.attributeNames();
for (String attributeName : attributeNames) {
setAttribute(attributeName, source.getAttribute(attributeName));
}
}
1.7 寻找依赖
如果一个 bean 有依赖 bean 的话,那么在初始化该 bean 时是需要先初始化它所依赖的 bean
// 获取依赖。
// 在初始化 bean 时解析 depends-on 标签时设置
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 迭代依赖
for (String dep : dependsOn) {
// 检验依赖的bean 是否已经注册给当前 bean 获取其他传递依赖bean
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册到依赖bean中
registerDependentBean(dep, beanName);
try {
// 调用 getBean 初始化依赖bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
在spring中有一个@DependsOn注解,它的作用是依赖加载,比如A对象要在B对象加载之后才能加载,那么可以在A上面加@DependsOn(value = "B")注解,就可以达到我们的要求。
- 通过我们前面从IoC容器中拿到的BeanDefinition,调用mbd.getDependsOn()方法,获取当前bean所有的依赖。
@Override
@Nullable
public String[] getDependsOn() {
return this.dependsOn;
}
- 遍历这些依赖,判断此依赖是否已注册给当前的Bean
// 保存的是bean与其依赖的映射关系:B - > A
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
//保存的是bean与其依赖的映射关系:A - > B
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
//为指定的Bean注入依赖的Bean
public void registerDependentBean(String beanName, String dependentBeanName) {
// A quick check for an existing entry upfront, avoiding synchronization...
//获取原始beanName
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
return;
}
// No entry yet -> fully synchronized manipulation of the dependentBeans Set
//先从容器中:bean名称-->全部依赖Bean名称集合找查找给定名称Bean的依赖Bean
synchronized (this.dependentBeanMap) {
//获取给定名称Bean的所有依赖Bean名称
dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
//为Bean设置依赖Bean信息
dependentBeans = new LinkedHashSet<>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
//把映射关系存入集合
dependentBeans.add(dependentBeanName);
}
//从容器中:bean名称-->指定名称Bean的依赖Bean集合找查找给定名称Bean的依赖Bean
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet<>(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
//把映射关系存入集合
dependenciesForBean.add(canonicalName);
}
}
套用上面的例子,如果 A@DependsOn(value = "B") ,也就是说A依赖于B,那么该方法registerDependentBean(dep, beanName)中,参数 dep 就是B,beanName 就是A。 这段代码中其实就是把bean之间的依赖关系注册到两个map中。
- dependentBeanMap 存入(B,A)
- dependenciesForBeanMap 存入(A,B)
- 递归调用getBean(),先生成依赖的bean
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
总结一下:
- 通过我们前面从IoC容器中拿到的BeanDefinition,调用mbd.getDependsOn()方法,获取当前bean所有的依赖。
- 遍历这些依赖,判断此依赖是否已注册给当前的Bean
- 递归调用getBean(),先生成依赖的bean
1.8 针对不同的scope进行bean的创建
// Create bean instance.
//创建单例Bean
if (mbd.isSingleton()) {
//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
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.
//显式地从容器单例模式Bean缓存中清除实例对象
destroySingleton(beanName);
throw ex;
}
});
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//创建多例Bean
else if (mbd.isPrototype()) {
//原型模式(Prototype)是每次都会创建一个新的对象
Object prototypeInstance = null;
try {
//加载前置处理,默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
//创建指定Bean对象实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//加载后置处理,默认的功能告诉IOC容器指定Bean的原型对象不再创建
afterPrototypeCreation(beanName);
}
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//要创建的Bean既不是Singleton也不是Prototype
//如:request、session、application等生命周期
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
//Bean定义资源中没有配置生命周期范围,则Bean定义不合法
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的实例对象
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);
}
}
1.1 单例模式实例化
关键代码
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
第一部分分析了从缓存中获取单例模式的 bean,但是如果缓存中不存在呢?则需要从头开始加载 bean,这个过程由 getSingleton() 实现。
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 全局加锁
synchronized (this.singletonObjects) {
// 从缓存中检查一遍
// 因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
Object singletonObject = this.singletonObjects.get(beanName);
// 为空,开始加载过程
if (singletonObject == null) {
// 省略 部分代码
// 加载前置处理
beforeSingletonCreation(beanName);
boolean newSingleton = false;
// 省略代码
try {
// 初始化 bean
// 这个过程其实是调用 createBean() 方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
// 省略 catch 部分
}
finally {
// 后置处理
afterSingletonCreation(beanName);
}
// 加入缓存中
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
// 直接返回
return singletonObject;
}
}
其实这个过程并没有真正创建 bean,仅仅只是做了一部分准备和预处理步骤,真正获取单例 bean 的方法其实是由 singletonFactory.getObject() 这部分实现,而 singletonFactory 由回调方法产生。那么这个方法做了哪些准备呢?关键代码在于 createBean(beanName, mbd, args),后面文章详细介绍 总结一下
- 再次检查缓存是否已经加载过,如果已经加载了则直接返回,否则开始加载过程。
- 调用 beforeSingletonCreation() 记录加载单例 bean 之前的加载状态,即前置处理。
- 调用参数传递的 ObjectFactory 的 getObject() 实例化 bean。
- 调用 afterSingletonCreation() 进行加载单例后的后置处理。
- 将结果记录并加入值缓存中,同时删除加载 bean 过程中所记录的一些辅助状态。
1.2 原型模式实例化
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
原型模式的初始化过程很简单:直接创建一个新的实例就可以了。 过程如下:
- 调用 beforeSingletonCreation() 记录加载原型模式 bean 之前的加载状态,即前置处理。
- 调用 createBean() 创建一个 bean 实例对象。
- 调用 afterSingletonCreation() 进行加载原型模式 bean 后的后置处理。
- 调用 getObjectForBeanInstance() 从 bean 实例中获取对象。
1.3 其他作用域
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);
}
核心流程和原型模式一样,只不过获取 bean 实例是由 scope.get() 实现,核心实现原理我们下一章具体分析
1.9 类型转换
程序到这里返回 bean 后基本已经结束了,通常对该方法的调用参数 requiredType 是为空的。 但是可能会存在这样一种情况:返回的 bean 是一个 String,但是 requiredType 却传入 Integer 类型,那么这时候本步骤就起作用了,它的功能是将返回的 bean 转换为 requiredType 所指定的类型。 当然,String 转换为 Integer 是最简单的转换,在 Spring 中提供了各种各样的转换器,用户可以扩展转换器来满足需求。
// 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;