一、前言
本文是笔者阅读Spring源码的记录文章,由于本人技术水平有限,在文章中难免出现错误,如有发现,感谢各位指正。在阅读过程中也创建了一些衍生文章,衍生文章的意义是因为自己在看源码的过程中,部分知识点并不了解或者对某些知识点产生了兴趣,所以为了更好的阅读源码,所以开设了衍生篇的文章来更好的对这些知识点进行进一步的学习。
二、简介
下面文章的内容,是基于上面衍生篇的内容来分析,如有不好理解内容,建议先查阅衍生篇内容。
1. DefaultSingletonBeanRegistry
我们首先需要了解DefaultSingletonBeanRegistry
类中的下面四个集合的作用如下
-
singletonObjects
: 用于保存BeanName和创建bean实例之间的关系,即缓存bean。 beanname -> instance -
singletonFactories
:用于保存BeanName和常见bean的工厂之间的关系。beanname-> ObjectFactory -
earlySingletonObjects
:也是保存BeanName和创建bean实例之间的关系,与singletonObjects 不同的是,如果一个单例bean被保存在此,则当bean还在创建过程中(比如 A类中有B类属性,当创建A类时发现需要先创建B类,这时候Spring又跑去创建B类,A类就会添加到该集合中,表示正在创建),就可以通过getBean方法获取到了,其目的是用来检测循环引用。 -
registeredSingletons
:用来保存当前所有已经注册的bean
2. BeanDefinition
BeanDefinition
是一个接口,在Spring 中存在三种实现: RootBeanDefinition
、ChildBeanDefinition
以及GenericBeanDefinition
。三种实现均继承了AbstractBeanDefinition
。顾名思义,BeanDefinition是bean的信息,一个BeanDefinition 描述和定义了创建一个bean需要的所有信息,属性,构造函数参数以及访问它们的方法。还有其他一些信息,比如这些定义来源自哪个类等等。
对于XML 配置方式的Spring方式来说, BeanDefinition 是配置文件 < bean >
元素标签在容器中的内容表示形式。< bean >
元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition 则提供了相应的beanClass、scope、lazyinit属性,BeanDefinition 和 < bean > 中的属性是一一对应的。其中RootBeanDefinition 是最常用的实现类,一般对应< bean > 元素标签。
类似下图的定义:
具体属性释义请参考 :
3. 搭建启动测试
我们新建一个项目,创建一个demoService。这里我为了省事就直接写了一个配置类加载。这个是为了引出我们来从getBean开始分析。
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(DemoConfig.class);
annotationConfigApplicationContext.getBean("demoService");
}
}
@Configuration
public class DemoConfig {
@Bean
public DemoService demoService(){
return new DemoServiceImpl();
}
}
annotationConfigApplicationContext.getBean("demoService");
最终会跳转到AbstractBeanFactory#doGetBean
。所以我们这里直接来分析 AbstractBeanFactory#doGetBean
三、doGetBean整体分析
AbstractBeanFactory#doGetBean
, 这个方法是一切的核心。
代码中是简略注释,后面对每一步进行详细解释。
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1. 提取出对应的beanName。
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 2. 尝试从缓存获取或者singletonFacotries中的ObjectFactory中获取。后续细讲
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 + "'");
}
}
// 3. 返回对应的实例,有时候存在诸如BeanFactory的情况并不直接返回实例本身,而是返回指定方法返回的实例。这一步主要还是针对FactoryBean的处理。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 4. 只有单例情况才会尝试解决循环依赖,原型模式直接抛出异常。因为原型模式无法解决循环依赖问题。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 递归到BeanFactory中检测
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 if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 如果不仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 6. 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 7. 寻找bean的依赖
// 获取初始化的依赖项
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 {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 8 针对不同的Scope 进行bean的创建
// 实例化依赖的bean便可以实例化mdb本身了
// singleton 模式的创建
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()) {
// Prototype 模式的创建
// 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 {
String scopeName = mbd.getScope();
// 指定scope上实例化bean
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.
// 9 类型转换
// 检查需要的类型是否符合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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
综上所属,doGetBean的 大体流程如下:
- 将传入的beanName 转化为合适的beanName。因为这里可能传入bean的别名,比如 FactoryBean 这里就是传入 “&beanName” , 这一步就会将其转化为 “beanName”
- 尝试从单例缓存中获取 bean,主要是尝试从 singletonObjects 和 singletonFactories 中获取实例。(这一步中还使用了 earlySingletonObjects 来判断循环依赖的问题)
- 如果第二步获取到了bean,则会针对处理 FactoryBean 这种特殊情况,以获取到正确的bean。(因为Factorybean 的话可能需要将其 getObject 方法的返回值作为bean注入到容器中)。
- 如果第二步没有获取到bean,则会检测其原型模式下的循环依赖情况,如果原型模式下有循环依赖,则直接抛出异常,因为原型模式下无法解决循环依赖。
- 如果第四步没有抛出异常,则会判断 当前BeanFactory 中是否包含该beanName 的定义信息,如果不包含,则会递归去 parentBeanFactory 中去寻找beanName的定义信息.
- 随后查询beanName 的 BeanDefinition 是否具有 父类的BeanDefinition, 如果有,则将 父类的一些属性和子类合并,形成一个新的BeanDefinition : mdb
- 获取mdb中的 depends-on 属性,优先将依赖的bean创建,随后再创建当前bean。
- 到这一步,则说明当前bean尚未创建,则会根据 singleton 或者 prototype 或其他逻辑,走不同的流程来创建bean
- 创建bean结束后,根据调用者需要的类型进行一个类型转换。比如调用者希望返回一个Integer,这里得到的结果却是String,则会进行一个类型的转换。
下面是对每一个步骤的详解。
四、doGetBean - 步骤详解
1. 转换对应beanName - transformedBeanName
final String beanName = transformedBeanName(name);
这一步的目的是为了去除 beanName 的别名,这里的name传入的可能是 bean的别名,或者是FactoryBean。所以需要一系列的解析,解析包括
- 去除 FactoryBean 的修饰符。也就是说如果 name = “&name” 会去除& 使得 name = “name”。
- 取指定alias所表示的最终beanName。比如别名A指向B的bean,则会返回B。
2. 尝试从缓存中加载单例 - getSingleton
Object sharedInstance = getSingleton(beanName);
单例的Spring在同一容器中只会创建一次(保存到单例缓存map中),后续再获取bean就直接从单例缓存中获取。这里的加载只是尝试加载,如果加载不成功则从singletonFactories 中加载。
因为在创建单例bean 的时候回存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,Spring 在创建bean的原则是不等bean 创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时需要依赖上一个bean,则直接使用ObjectFactory。
代码逻辑如下:
- 尝试从
singletonObjects
中获取。获取不到说明该bean尚未创建成功。 -
isSingletonCurrentlyInCreation
返回 true,则说明当前bean 的创建过程存在循环依赖,下面的逻辑就是为了尝试解决循环依赖 - 尝试从
earlySingletonObjects
中获取,获取不到说明该bean并未在创建过程中。(为了解决循环依赖的问题) - 当
allowEarlyReference = true
时,这个是针对循环引用的操作,是允许循环引用。 - 随后 从
singletonFactories
中加载beanFactory,并将结果保存到earlySingletonObjects
中,同时将singletonFactories
中关于bean的定义移除。(earlySingletonObjects
和singletonFactories
互斥)
具体代码如下:
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 尝试从单例缓存中加载。
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 如果加载失败,则加锁进行接下来的处理
synchronized (this.singletonObjects) {
// 如果此时bean正在加载,则直接将singletonObject 返回。
singletonObject = this.earlySingletonObjects.get(beanName);
// allowEarlyReference = true 才会允许循环依赖
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;
}
这里需要注意的是从 singletonFactories 中获取的是ObjectFactory。随后从中获取ObjectFactory.getObject()。 这里的目的是为了解决循环依赖,
3. 从bean 的实例中获取对象 - getObjectForBeanInstance
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
当我们结束上一步之后,经过 sharedInstance != null && args == null 的判断后就会调用该方法。
作为上一步获取到的结果 sharedInstance 。我们需要判断其是否是FactoryBean 的 实现类,如果是,则需要将其getObject() 的结果注入。所以该方法的功能简单来说就是用来检测当前bean是否是FactoryBean类型的bean,如果是,则调用其getObject() 方法,并将其返回值作为bean。
关于FactoryBean的内容请参考 :
代码逻辑大体如下:
- 判断是否需要获取
FactoryBean
实例。 通过BeanFactoryUtils.isFactoryDereference(name)
来判断
判断name 是否以&
开头。如果是则说明是想获取 FactoryBean 的实例,所以经过简单校验后就直接返回beanInstance。 - 经过第一步,现在可以确定,当前bean不是为了获取FactoryBean实现类,那么这个bean还可能是普通bean或者FactoryBean。
if (!(beanInstance instanceof FactoryBean))
判断如果不是FactoryBean则没必要进行下一步处理,直接返回即可。 - 这一步可以确定,这里的bean是 FactoryBean类型,并且name 是“beanName”,表明是想获取bean实例,而不是beanFactory实例,则将解析bean的工作委托给
getObjectFromFactoryBean
完成。getObjectFromFactoryBean
方法对FactoryBean的解析还是在 中完成。(getObjectFromFactoryBean 这一步调用了ObjectFactory的后置处理器)
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
// 1. 检测name 是否是想获取 工厂类(name 以 & 开头)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
// 以&开头又不是FactoryBean实现类,则抛出异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
}
if (mbd != null) {
mbd.isFactoryBean = true;
}
return beanInstance;
}
// 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.
// 2. 判断如果beanInstance 不是 FactoryBean,就直接返回
if (!(beanInstance instanceof FactoryBean)) {
return beanInstance;
}
// 3. 到这一步就可以确定,当前beanInstance 是FactoryBean,并且需要获取getObject() 的结果
Object object = null;
if (mbd != null) {
mbd.isFactoryBean = true;
}
else {
// 尝试从缓存中加载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 检测 beanDefinitionMap中也就是所有已经加载的类中检测是否定义beanName
if (mbd == null && containsBeanDefinition(beanName)) {
// 合并父类bean 定义的属性
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 4. 这一步中对FactoryBean进行了解析。
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
getObjectFromFactoryBean
方法中 调用 doGetObjectFromFactoryBean
方法进行了解析。
上面已经说了,因为这里的bean是FactoryBean,且并不是为了获取FactoryBean实例,所以会调用factory.getObject() 方法将得到的bean返回。
getObjectFromFactoryBean
代码如下
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 判断是否是单例模式
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
// 尝试从缓存中获取
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 在这个方法中进行解析
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)
// 因为是单例模式,所以要保证变量的全局唯一。所以这里如果缓存中已经创建好了bean则替换为已经创建好的bean
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
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;
}
}
....
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 {
// 直接调用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;
}
4 原型模式的依赖检查 - isPrototypeCurrentlyInCreation
if (isPrototypeCurrentlyInCreation(beanName)) {
在衍生篇中对循环依赖有过结介绍,简而言之就是 单例模式下才会尝试去解决循环依赖的问题,而原型模式则无法解决。也就是 isPrototypeCurrentlyInCreation
返回true,则抛出异常。
需要注意的是还有一个 方法是 判断单例模式的依赖检查 : isSingletonCurrentlyInCreation
5 检测 parentBeanFactory - if (parentBeanFactory != null && !containsBeanDefinition(beanName))
这一步的逻辑比较简单,如下:
- 首先通过
containsBeanDefinition(beanName)
方法判断当前beanFactory中是否有bean的定义,如果有,皆大欢喜。直接进入下一步。 - 如果没有,且 parentBeanFactory 不为空,则会通过递归的方式,尝试从 parentBeanFactory 中加载bean定义
// 5. 如果 beanDefinitionMap 中也就是在所有已经加载的类中不包含beanName,则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 递归到BeanFactory中检测
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 if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
其中 DefaultListableBeanFactory#containsBeanDefinition
代码如下
@Override
public boolean containsBeanDefinition(String beanName) {
Assert.notNull(beanName, "Bean name must not be null");
return this.beanDefinitionMap.containsKey(beanName);
}
6 将当前 beanName 的 BeanDefinition 和父类BeanDefinition 属性进行一个整合
BeanDefinition 顾名思义,就是关于bean 的定义信息。通过xml的bean定义可以很清楚的看到一些属性定义。
所以这一步就是检查当前 BeanDefinition 是否有父BeanDefinition ,如果有将一些属性和当前bean合并,生成一个 RootBeanDefinition。
推荐阅读:
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
- getMergedLocalBeanDefinition -> getMergedBeanDefinition -> getMergedBeanDefinition。
这里直接来看 getMergedBeanDefinition 方法。
首先,mdb 即 MergedBeanDefinition 的缩写,即一个合并的beanDefinition。
protected RootBeanDefinition getMergedBeanDefinition(
String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
throws BeanDefinitionStoreException {
synchronized (this.mergedBeanDefinitions) {
RootBeanDefinition mbd = null;
RootBeanDefinition previous = null;
// Check with full lock now in order to enforce the same merged instance.
if (containingBd == null) {
mbd = this.mergedBeanDefinitions.get(beanName);
}
if (mbd == null || mbd.stale) {
previous = mbd;
// 判断如果parentName为空则没必要进行合并了,直接克隆返回即可
if (bd.getParentName() == null) {
// Use copy of given root bean definition.
if (bd instanceof RootBeanDefinition) {
mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
}
else {
mbd = new RootBeanDefinition(bd);
}
}
else {
// Child bean definition: needs to be merged with parent.
BeanDefinition pbd;
try {
// 转换beanName
String parentBeanName = transformedBeanName(bd.getParentName());
// 递归调用,解析更上层的parent
if (!beanName.equals(parentBeanName)) {
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 a ConfigurableBeanFactory 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);
mbd.overrideFrom(bd);
}
// Set default singleton scope, if not configured before.
if (!StringUtils.hasLength(mbd.getScope())) {
mbd.setScope(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());
}
// Cache the merged bean definition for the time being
// (it might still get re-merged later on in order to pick up metadata changes)
if (containingBd == null && isCacheBeanMetadata()) {
this.mergedBeanDefinitions.put(beanName, mbd);
}
}
if (previous != null) {
copyRelevantMergedBeanDefinitionCaches(previous, mbd);
}
return mbd;
}
}
7 寻找依赖
这一步也是针对 BeanDefinition 的 depends-on
属性来说的(对应注解则是 @DependsOn
。主要是 优先加载Bean 的 depends-on依赖。
因为bean 的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺寻中,在初始化某一个bean的时候首先会初始化这个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);
}
}
}
注意:@DependsOn
:注解是在另外一个实例创建之后才创建当前实例,也就是,最终两个实例都会创建,只是顺序不一样@ConditionalOnBean
:注解是只有当另外一个实例存在时,才创建,否则不创建,也就是,最终有可能两个实例都创建了,有可能只创建了一个实例,也有可能一个实例都没创建
8 针对不同的Scope 进行bean的创建
这里很明显,针对不同的Scope进行不同的初始化操作。创建bean 的过程也很复杂,这里打算开新篇讲解(暂未成篇)。
下面代码就是根据 Singleton、Prototype 或者其他Scope 走不同的流程创建bean。
// Create bean instance.
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);
}
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);
}
}
9 类型转换
到这里整个流程基本就结束了。通常对该方法的调用参数 requiredType 是null,。但某些情况可能会出现返回的bean是个String类型,但是requiredType 传入的却是Integer类型,这时候就会触发这一步的操作,将String类型转换为Integer类型。
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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}