本文主要基于 Spring 5.0.6.RELEASE
摘要: 原创出处 http://cmsblogs.com/?p=todo 「小明哥」,谢谢!
作为「小明哥」的忠实读者,「老艿艿」略作修改,记录在理解过程中,参考的资料。
1. createBean 抽象方法
在上篇博客 《【死磕 Spring】—— IoC 之加载 Bean:分析各 scope 的 Bean 创建》 中,有一个核心方法没有讲到, #createBean(String beanName, RootBeanDefinition mbd, Object[] args)
方法,代码如下:
// AbstractBeanFactory.java |
- 该方法定义在 AbstractBeanFactory 中,其含义是根据给定的 BeanDefinition 和
args
实例化一个 Bean 对象。 - 如果该 BeanDefinition 存在父类,则该 BeanDefinition 已经合并了父类的属性。
- 所有 Bean 实例的创建,都会委托给该方法实现。
- 该方法接受三个方法参数:
beanName
:bean 的名字。mbd
:已经合并了父类属性的(如果有的话)BeanDefinition 对象。args
:用于构造函数或者工厂方法创建 Bean 实例对象的参数。
2. createBean 默认实现
该抽象方法的默认实现是在类 AbstractAutowireCapableBeanFactory 中实现,代码如下:
// AbstractAutowireCapableBeanFactory.java |
过程如下:
<1>
处,解析指定 BeanDefinition 的 class 属性。<2>
处,处理override
属性。<3>
处,实例化的前置处理。<4>
处,创建 Bean 对象。
详细解析,每 <x>
处,对应下面的 「2.x」 。
2.1 解析指定 BeanDefinition 的 class
// AbstractAutowireCapableBeanFactory.java |
#resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
方法,主要是解析 bean definition 的 class 类,并将已经解析的 Class 存储在 bean definition 中以供后面使用。- 如果解析的 class 不为空,则会将该 BeanDefinition 进行设置到
mbdToUse
中。这样做的主要目的是,以为动态解析的 class 是无法保存到共享的 BeanDefinition 中。
详细解析,见 TODO
2.2 处理 override 属性
大家还记得 lookup-method
和 replace-method
这两个配置功能?在博客 《【死磕 Spring】—— IoC 之解析 methodOverrides
属性中。
我们知道在 bean 实例化的过程中如果检测到存在 methodOverrides
,则会动态地位为当前 bean 生成代理并使用对应的拦截器为 bean 做增强处理。具体的实现我们后续分析,现在先看 mbdToUse.prepareMethodOverrides()
代码块,都干了些什么事,代码如下:
// AbstractBeanDefinition.java |
如果存在
methodOverrides
,则获取所有的 override method ,然后通过迭代的方法一次调用#prepareMethodOverride(MethodOverride mo)
方法。代码如下:// AbstractBeanDefinition.java
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
if (count == 0) {
throw new BeanDefinitionValidationException(
"Invalid method override: no method with name '" + mo.getMethodName() +
"' on class [" + getBeanClassName() + "]");
} else if (count == 1) {
// Mark override as not overloaded, to avoid the overhead of arg type checking.
mo.setOverloaded(false);
}
}- 根据方法名称,从 class 中获取该方法名的个数:
- 如果个数为 0 ,则抛出 BeanDefinitionValidationException 异常。
- 如果个数为 1 ,则设置该重载方法没有被重载。
- 若一个类中存在多个重载方法,则在方法调用的时候还需要根据参数类型来判断到底重载的是哪个方法。在设置重载的时候其实这里做了一个小小优化,那就是当
count == 1
时,设置overloaded = false
,这样表示该方法没有重载。这样,在后续调用的时候,便可以直接找到方法而不需要进行方法参数的校验。
- 根据方法名称,从 class 中获取该方法名的个数:
诚然,其实 mbdToUse.prepareMethodOverrides()
代码块,并没有做什么实质性的工作,只是对 methodOverrides
属性做了一些简单的校验而已。
2.3 实例化的前置处理
#resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
方法的作用,是给 BeanPostProcessors 后置处理器返回一个代理对象的机会。其,实在调用该方法之前 Spring 一直都没有创建 bean ,那么这里返回一个 bean 的代理类有什么作用呢?作用体现在后面的 if
判断,代码如下:
// AbstractBeanDefinition.java |
- 如果代理对象不为空,则直接返回代理对象,这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
#resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
方法,代码如下:// AbstractAutowireCapableBeanFactory.java
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 前置
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 后置
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}- 这个方法核心就在于
applyBeanPostProcessorsBeforeInstantiation()
和applyBeanPostProcessorsAfterInitialization()
两个方法,before 为实例化前的后处理器应用,after 为实例化后的后处理器应用。 - 由于本文的主题是创建 bean ,关于 Bean 的增强处理后续 LZ 会单独出博文来做详细说明。
- 这个方法核心就在于
详细解析,见 TODO
2.4 创建 Bean
如果没有代理对象,就只能走常规的路线进行 bean 的创建了,该过程有 #doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
方法来实现。代码如下:
// AbstractAutowireCapableBeanFactory.java |
整体的思路:
<1>
处,如果是单例模式,则清除缓存。- 详细解析,见 TODO
<2>
处,调用#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)
方法,实例化 bean ,主要是将 BeanDefinition 转换为org.springframework.beans.BeanWrapper
对象。<3>
处,MergedBeanDefinitionPostProcessor 的应用。- 详细解析,见 TODO
<4>
处,单例模式的循环依赖处理。<5>
处,调用#populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw)
方法,进行属性填充。将所有属性填充至 bean 的实例中。<6>
处,调用#initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
方法,初始化 bean 。<7>
处,依赖检查。- 详细解析,见 TODO
<8>
处,注册 DisposableBean 。- 详细解析,见 TODO
3. 小结
#doCreateBean(...)
方法,完成 bean 的创建和初始化工作,内容太多,这里就只列出整体思路。下文开始,将该方法进行拆分进行详细讲解,分布从以下几个方面进行阐述:
#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)
方法,实例化 bean 。- 循环依赖的处理。
#populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw)
方法,进行属性填充。#initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)
方法,初始化 Bean 。