Spring系列-2 Bean的生命周期
作为Spring系列的第二篇,本文结合容器的启动流程介绍**单例Bean的生命周期**,包括Bean对象的创建、属性设置、初始化、使用、销毁等阶段;在此过程中会介绍Spring用于操作Bean或者BeanDefinition的相关扩展接口。文章重心在于介绍整个Bean生命周期,不拘泥于每个阶段的细节。
背景:
作为Spring系列的第二篇,本文结合容器的启动流程介绍单例Bean的生命周期,包括Bean对象的创建、属性设置、初始化、使用、销毁等阶段;在此过程中会介绍Spring用于操作Bean或者BeanDefinition的相关扩展接口。
文章重心在于介绍整个Bean生命周期,不拘泥于每个阶段的细节;因此本文中会常见到“主线逻辑”这个关键词,请读者不要对此反感。
容器的启动流程请参考:Spring系列-1 启动流程
1.Bean的生命周期
本文介绍单例Bean的生命周期,本文后续提到中Bean对象默认指代单例Bean。
1.1 流程图
每个Bean的生命周期都包括:实例化、属性设置、初始化、入单例池、销毁等阶段,整个流程可表示为:
上图中Bean的生命周期主流程可以分为4个部分:
[1] 实例化阶段
实例化阶段的核心目的是生成Bean对象,过程包括构造函数的推断与选择、通过反射调用目标构造函数实例化Bean对象。
Spring在框架中引入了InstantiationAwareBeanPostProcessor接口,提供了操作对象实例化的切入点;用户可以继承InstantiationAwareBeanPostProcessor接口自定义实例化对象过程。
[2] 属性设置阶段
属性设置阶段的核心任务是对已实例化的Bean对象根据配置进行属性设置。
InstantiationAwareBeanPostProcessor接口的postProcessProperties方法也提供给了用户干扰属性设置的能力。
MergedBeanDefinitionPostProcessor接口提供了操作Beandefinition信息的能力,也可以基于Beandefinition提取相关信息;如AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor在实现依赖注入时使用MergedBeanDefinitionPostProcessor进行依赖注入前的数据准备工作。
[3] 初始化阶段
初始化阶段是Spring框架为Bean对象自定义的一个阶段,目的在于当Bea对象完成实例化和属性注入后可以执行一些扩展方法。
该阶段按执行顺序包括:Aware接口的执行与相关Aware属性的设置、执行BeanPostProcessor的前置方法、执行初始化方法、执行BeanPostProcessor的后置方法。
其中,BeanPostProcessor的后置方法是依赖注入、AOP等实现原理(后续Spring系列文章中会反复见到BeanPostProcessor的后置方法)。
该阶段的核心逻辑是执行初始化方法,按照调用顺序包括:InitializingBean接口的afterPropertiesSet()方法 和
xml配置文件中通过Init-method属性指定的初始化方法。
[4] 销毁阶段
当容器被注销时,会销毁单例池中的Bean对象,此时进入Bean对象生命周期的销毁阶段,该阶段按照执行顺序包括:DisposableBean的destroy()方法和xml配置文件中通过destory-method属性指定的方法。
1.2 Bean生命周期方法
Bean生命周期方法是Bean对象级别的方法,即每种类型的Bean有自己的方法(仅作用于自己),区别于Spring系统级别的方法(如BeanpostProcessor)作用于所有Bean对象。
1.2.1 Aware接口
Aware接口逻辑较为简单,用于向Bean对象种设置某种类型的属性,如下是BeanFactoryAware接口定义:
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
案例如下:
public class ComponentA implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public Object getBean(String beanName) {
return beanFactory.getBean(beanName);
}
}
1.2.2 InitializingBean与DisposableBean
InitializingBean接口用于指定初始化逻辑,DisposableBean用于指定销毁逻辑:
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
void destroy() throws Exception;
}
1.2.3 SmartInitializingSingleton
public interface SmartInitializingSingleton {
void afterSingletonsInstantiated();
}
SmartInitializingSingleton在Spring容器完成所有非延迟单例Bean的注入到IOC容器后执行。
用户可通过SmartInitializingSingleton定义Bean注入到IOC后的自定义过程。
1.3 钩子函数
Spring提供这些钩子函数是为了提高Spring框架的扩展能力,基于Spring构造Bean对象的主流程衍生出新功能,
如依赖注入或者AOP代理等。
钩子函数作为Spring系统级别的方法作用于所有Bean对象。
1.3.1 MergedBeanDefinitionPostProcessor
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}
MergedBeanDefinitionPostProcessor接口除去因继承BeanPostProcessor引入的接口外,只有一个postProcessMergedBeanDefinition方法:通过beanDefinition,可修改beanDefinition以影响后续的属性设置;也可以从beanDefinition中提取信息做前置准备。
值得注意的是该接口不具备直接操作Bean对象的能力,原因如下:(1) 入参中没有携带Bean对象; (2) 此时Bean对象虽然已经被实例化,但是尚未加入三级缓存中, 即无法通过BeanFactory从IOC中获取该Bean对象。
1.3.2 BeanPostProcessor(BPP)
BeanPostProcessor中存在两个方法,postProcessBeforeInitialization和postProcessAfterInitialization:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
从名称可以看出postProcessBeforeInitialization在初始化方法之前执行,postProcessAfterInitialization在初始化方法之后执行。
postProcessBeforeInitialization和postProcessAfterInitialization均提高了直接修改Bean对象的能力:方法的入参上Bean对象和beanName, 返回值为修改后的Bean对象。需要注意:二者的执行时机都在Bean对象已完成实例化与属性赋值后。
其中,postProcessAfterInitialization方法的扩展能力被Spring使用得淋漓尽致;依赖注入、AOP等功能都是基于该方法的扩展能力而实现。
1.3.3 InstantiationAwareBeanPostProcessor(IABPP)
InstantiationAwareBeanPostProcessor接口的定义如下:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
}
// 除此之外,还有个postProcessPropertyValues方法,作用同postProcessProperties。
// 因被@Deprecated注解,本文选择进行忽略
InstantiationAwareBeanPostProcessor为扩展实例化过程提供了postProcessBeforeInstantiation和postProcessAfterInstantiation两个方法,为扩展属性设置过程提供了postProcessProperties方法。
基于InstantiationAwareBeanPostProcessor接口的设计目的,对该接口的说明需要结合Bean对象构建过程进行介绍,否则会失去其上下文意义(如同单词之于语句)。
postProcessBeforeInstantiation
postProcessBeforeInstantiation方法的入参为beanName和Bean对象的类型,用户可基于此构建Bean对象并返回,也可返回null(默认返回null);当有对象返回时,将走扩展流程而不是按照Bean生命周期的主体流程来创建Bean对象。
创建Bean对象的createBean方法中主线逻辑如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ⚠️: 省略无关逻辑与try-catch等代码...
// ⚠️:步骤1:调用resolveBeforeInstantiation方法构造Bean对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果bean对象不为null,直接返回
if (bean != null) {
return bean;
}
// ⚠️:步骤2:调用doCreateBean方法构造Bean对象并返回
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
这里我们关注的重点在于resolveBeforeInstantiation(beanName, mbdToUse)
方法,该方法的主线逻辑如下:
// ... 省略if分支,突出主线逻辑
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
return bean;
}
该方法逻辑较为简单,通过applyBeanPostProcessorsBeforeInstantiation调用IABPP的postProcessBeforeInstantiation方法构建Bean对象(遍历IOC中的IABPP对象,并调用其postProcessBeforeInstantiation方法;返回一个非空的对象,否则返回空),如果为空则直接放回;否则通过applyBeanPostProcessorsAfterInitialization调用BPP的postProcessAfterInitialization方法操作Bean对象。
此时,Bean的构建过程如下所示:
因为,AOP和依赖注入的实现逻辑都在BPP的postProcessAfterInitialization方法,上述设计使得自定义的Bean对象仍然可以拥有Spring框架的依赖注入和AOP等功能。
postProcessAfterInstantiation和postProcessProperties
对postProcessAfterInstantiation和postProcessProperties二者的介绍放在一起是因为二者都发生在populate()方法中,可以从代码层面认为二者隶属于属性设置过程,populateBean方法的主线逻辑如下:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ⚠️:1.调用postProcessAfterInstantiation
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// ... pvs对象修改
// ⚠️:2.调用postProcessProperties
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
pvs = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
}
// ... check
// ⚠️:3.根据pvs的信息对Bean对象设置属性
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
populateBean方法的核心功能是进行属性设置,步骤可分为如下三步:
[1] 调用postProcessAfterInstantiation;
[2] 根据配置信息构造pvs对象,调用IABPP对象的postProcessProperties方法修改pvs对象;
[3] 根据pvs的信息对Bean对象设置属性.
其中:步骤[1]中遍历IOC容器中的IABPP对象,并调用其postProcessAfterInstantiation方法,当所有的调用结果都返回true时,继续执行步骤[2]和步骤[3]进行属性的设置;否则跳过步骤[2]和[3],即不会执行属性设置流程.
2.案例介绍
略
3.原理
本章节基于Spring源码介绍Bean对象的构建过程。
3.1 触发时机
如Spring系列-1 启动流程文中介绍:在Spring容器启动之初先向IOC容器中注入Spring框架内置的组件对象、BeanFactory、BeanPostProcessor等Bean对象等, 之后初始化所有的非懒加载的单例Bean对象。过程中,当遇到依赖的Bean对象时,优先构造被依赖的Bean对象(无论是否时懒加载Bean).
AbstractBeanFactory.refresh()方法:
public void refresh() throws BeansException, IllegalStateException {
//...
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
//...
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//...
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
preInstantiateSingletons方法:
DefaultListableBeanFactory类提供的preInstantiateSingletons方法会加载所有的非lazy单例Bean,代码如下所示:
public void preInstantiateSingletons() throws BeansException {
//⚠️:说明:为突出Bean的主线逻辑,省去了FactoryBean逻辑以及一些包装的内容。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
getBean(beanName);
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
smartSingleton.afterSingletonsInstantiated();
}
}
}
该方法对beanDefinitionNames进行了两次遍历:第一次遍历时对于非延迟的单例Bean调用getBean(beanName)
方法构造Bean对象;第二次对于实现了SmartInitializingSingleton接口的Bean对象调用其afterSingletonsInstantiated方法,执行用户的自定义操作。
3.2 getBean和doGetBean
getBean方法:
该方法可以根据beanName获取Bean对象,如果对象不存在则创建该Bean对象。
public Object getBean(String name) throws BeansException {
// 以do开头的方法,一般是实际干活的
return doGetBean(name, null, null, false);
}
注意第二个参数是null,即调用doGetBean方法时,Class requiredType参数为null。
doGetBean方法:
doGetBean主线逻辑如下所示:
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) {
String beanName = transformedBeanName(name);
Object beanInstance;
// ⚠️1:parentBeanFactory.getBean(nameToLookup)
// ⚠️2:checkMergedBeanDefinition(mbd, beanName, args);
// ⚠️3:优先构造被依赖的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);
getBean(dep);
}
}
// ⚠️4: 构造Bean对象
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
return createBean(beanName, mbd, args);
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//...
} else {
//...
}
// ⚠️5:类型校验&&适配
return adaptBeanInstance(name, beanInstance, requiredType);
}
doGetBean的主线逻辑可以分为如下五个步骤:
[1] 从父亲容器中获取Bean对象
如果当前容器中不存在beanName对应的Bean定义,Spring会尝试通过调用父容器的getBean方法获取Bean对象。
注意:父容器不能获取子容器中的Bean对象, 而子容器可以获取父容器中的Bean对象(因为子容器通过parentBeanFactory属性持有了父容器的引用)。
[2] 校验BeanDefinition
校验逻辑在checkMergedBeanDefinition方法中实现。
[3] 处理依赖关系
如果当前beanName对应的Bean对象存在依赖的Bean时,优先通过getBean方法处理被依赖的Bean对象。
如果存在相互依赖,则抛出BeanCreationException异常。
[4] 构造Bean对象
根据Bean的类型走不同的构造流程,当Bean为单例时,执行如下逻辑构造Bean对象:
sharedInstance = getSingleton(beanName, () -> createBean(beanName, mbd, args));
// getObjectForBeanInstance方法是为了适配FactoryBean类型的对象
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
上述lambda表达式用于传参给FactoryBean, 当执行该FactoryBean对象的getBean时会调用该表达式,因此
getSingleton方法的主线逻辑可以被整合为:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
beforeSingletonCreation(beanName);
singletonObject = createBean(beanName, mbd, args);
afterSingletonCreation(beanName);
addSingleton(beanName, singletonObject);
}
return singletonObject;
}
首先尝试从单例池中根据beanName获取Bean对象,如果不为空——直接返回;否则调用createBean(beanName, mbd, args)
构造Bean对象(前后环绕着beforeSingletonCreation和afterSingletonCreation方法)。addSingleton(beanName, singletonObject)
用于将创建好的对象加入到单例池中并清理缓存。
[5] 类型校验和转换
adaptBeanInstance方法会根据requiredType确定是否执行类型校验和转换, 校验失败时抛出BeanNotOfRequiredTypeException异常:
<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) convertedBean;
} catch (TypeMismatchException ex) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
当requiredType为null时,不经过任何处理直接返回。在上述getBean调用doGetBean方法时传递的requiredType为null, 因此在Spring容器初始化阶段构造的Bean对象不会经过类型校验和转换。
3.3 createBean和doCreateBean
createBean方法:
创建Bean对象的createBean方法中主线逻辑如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// ⚠️: 省略无关逻辑与try-catch等代码...
// ⚠️:步骤1:调用resolveBeforeInstantiation方法构造Bean对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果bean对象不为null,直接返回
if (bean != null) {
return bean;
}
// ⚠️:步骤2:调用doCreateBean方法构造Bean对象并返回
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
主线逻辑分为两个步骤:(1) 调用resolveBeforeInstantiation方法构造Bean对象和 (2) 调用doCreateBean方法构造Bean对象。其中resolveBeforeInstantiation方法在请参考1.3.3 InstantiationAwareBeanPostProcessor
节中的内容。
doCreateBean方法:
该方法的主线逻辑如下所示:
// 省略无关逻辑
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// ...
// ⚠️:1.实例化Bean对象
// Instantiate the bean.
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// ⚠️:2.将半成品对象加入三级缓存
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// ⚠️:3.Bean对象的属性设置
populateBean(beanName, mbd, instanceWrapper);
// ⚠️:4.Bean对象的初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
// ⚠️:5.注册DisposableBean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
// ⚠️:6.返回对象
return exposedObject;
}
doCreateBean实际承担了构造Bean对象的任务,包括:
[1] 调用createBeanInstance实例化Bean对象;
[2] 将半成品的Bean对象加入三级缓存;
[3] 对Bean对象进行属性设置;
[4] 对Bean对象执行初始化;
[5] 注册实现了DisposableBean接口的Bean对象;
[6] 返回构建完成的Bean对象。
3.4 实例化
createBeanInstance方法:
通过createBeanInstance实例化Bean对象,代码如下所示:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1.校验Bean对象的字节码对象:必须为public且存在public的构造方法
// 2.Supplier接口或者工厂方法不为空的,使用对应的构造流程构造Bean对象
// 3.使用构造函数构造Bean对象 {
//resolved表示构造函数是否已经解析完成;autowireNecessary表示是否需要自动装配
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
} else {
return instantiateBean(beanName, mbd);
}
}
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
return instantiateBean(beanName, mbd);
}
}
该方法主线逻辑有以下三个步骤:
[1] 校验Bean对象的字节码对象:必须为public且存在public的构造方法;
[2] Supplier接口或者工厂方法不为空的,使用对应的构造流程构造Bean对象;
[3] 使用Bean的构造函数构造Bean对象。
其中第三步为本文感兴趣的部分,整体上看:根据Bean的具体情况选择调用autowireConstructor
或者instantiateBean
方法进行实例化;并引入了两个标记变量:resolved表示构造函数是否已经完成过解析;autowireNecessary表示是否调autowireConstructor
方法进行实例化。
另外,BeanDefinition对象的constructorArgumentsResolved属性用于标记是否已进行过构造函数推断(true表示使用autowireConstructor方法实例化Bean对象,false表示使用instantiateBean方法),是一种优化:当同一个BeanDefinition被多次用于构造Bean对象时,不需要执行重复的推断步骤;该属性针对的是Prototype类型的Bean对象,对单例Bean没有优化的意义。
determineConstructorsFromBeanPostProcessors(beanClass, beanName)
也是一个钩子函数,用于干预构造函数的选择:
如果用户自定义了SmartInstantiationAwareBeanPostProcessor实现类,且返回了通过determineConstructorsFromBeanPostProcessors(beanClass, beanName)
为对应的bean确定了构造函数,则使用该构造函数实例化Bean对象。
因此,对于单例Bean对象上述逻辑可以简化为:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
} else {
return instantiateBean(beanName, mbd);
}
}
if (mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR
|| mbd.hasConstructorArgumentValues()
|| !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, null, args);
}
return instantiateBean(beanName, mbd);
}
其实,不看具体实现而仅从上述代码逻辑也可以推断出来:instantiateBean(beanName, mbd)
表示调用无参构造函数实例化对象,而autowireConstructor(beanName, mbd, ctors, args)
使用有参构造函数。
autowireConstructor方法封装了一个重要的概念,构造函数推断:
(1)当存在使用@Autowired注解的构造函数时,使用被@Autowired注解的构造函数实例化对象;
(2)当只有一个构造函数时,使用该构造函数;
(3)当存在多个构造函数且存在默认构造函数时,使用默认构造函数;
(4)当存在多个构造函数且不存在默认构造函数时,抛出异常。
3.5 populateBean
因介绍InstantiationAwareBeanPostProcessor而前置了该部分内容,请参考1.3.3 InstantiationAwareBeanPostProcessor
节中的内容。
3.6 初始化
initializeBean方法:
该方法的源码如下:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// ⚠️:1.调用Aware接口
invokeAwareMethods(beanName, bean);
// ⚠️:2.调用BPP的postProcessBeforeInitialization方法
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// ⚠️:3.执行初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
// ⚠️:4.调用BPP的postProcessAfterInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
// ⚠️:5.调用BPP的postProcessBeforeInitialization方法
return wrappedBean;
}
主线逻辑分为如下五个步骤:
(1) 调用Aware接口,进行Aware相关属性的设置;
(2) 调用BPP的postProcessBeforeInitialization方法;
(3) 执行初始化方法;
(4) 调用BPP的postProcessAfterInitialization方法;
(5) 调用BPP的postProcessBeforeInitialization方法。
invokeInitMethods方法:
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// ⚠️:1.调用InitializingBean的afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
((InitializingBean) bean).afterPropertiesSet();
}
// ⚠️:2.调用xml配置中通过init-method属性指定的初始化方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
其他步骤在上文中均已进行过介绍,此处不再赘述。
更多推荐
所有评论(0)