开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天
Spring Bean生命周期,从入门到进阶:
【Spring Bean生命周期】小白也能看懂的入门篇
【Spring Bean生命周期】高手如何解读源码(一)-资源的扫描和注册
1 Bean生命周期的核心动作
上一节讲了第一部分Bean的扫描以及注册,本文主要讲解第二部分Spring Bean生命周期,主要包含下面四个主要动作:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 销毁 Destruction
依照黄金圈法则(why->what->how),在去了解Spring是如何实现之前,我们先了解下为什么要有这些动作?
我们知道,普通Java类是先初始化->再实例化的:
类的初始化:是完成程序执行前的准备工作。在这个阶段,静态的(变量,方法,代码块)会被执行。同时在会开辟一块存储空间用来存放静态的数据。初始化只在类加载的时候执行一次。
类的实例化:是指创建一个对象的过程。这个过程中会在堆中开辟内存,将一些非静态的方法,变量存放在里面。在程序执行的过程中,可以创建多个对象,既多次实例化。每次实例化都会开辟一块新的内存
而Spring Bean是先实例化->再初始化:
Bean的实例化:等同于 类的实例化
Bean的初始化:是完成Bean使用前的准备工作。主要包含 执行Aware相关接口的set方法注入依赖,执行BeanPostProcessors的前置方法,@PostConstruct注解方法执行,InitializingBean接口实现类(组件)的初始化方法afterPropertiesSet执行,自己指定的init-method方法执行等
一句话理解,初始化是在为正式使用做准备,类初始化的结果是Jvm可用,Bean初始化的结果是用户程序可用。
接着上文,Bean生命周期触发点,在AbstractApplicationContext
类的refresh()
方法中,执行到finishBeanFactoryInitialization(beanFactory)
时完成Bean生命周期的动作。该方法会实例化所有剩余的非懒加载单例 bean。除了:
- 一些内部的 bean
- 实现了 BeanFactoryPostProcessor 接口的 bean、
- 实现了 BeanPostProcessor 接口的 bean,
- 其他的非懒加载单例 bean
都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。我们看下代码执行路径:
// ConfigurableListableBeanFactory接口
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
......
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
// DefaultListableBeanFactory类
@Override
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非惰性Bean的初始化
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
......
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
......
可以看到核心方法有两个:
方法一:getMergedLocalBeanDefinition(beanName)
, 将前面扫描获取的各种BeanDefinition子类统一转化成RootBeanDefinition类型,作为实例化的入口。
比较常见的:
如果我们使用 XML 配置来注册 bean,则该 bean 定义会被封装成:GenericBeanDefinition;
如果我们使用注解的方式来注册 bean,也就是<context:component-scan /> + **@Compoment,则该 bean 定义会被封装成 ScannedGenericBeanDefinition。**
方法二:getBean(beanName)
,包括Bean的实例化,属性注入和初始化等动作。
// AbstractBeanFactory类
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
其中getBean()
的流程如图:
// AbstractAutowireCapableBeanFactory类
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 替换成自己的代理Bean
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
......
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
其中,resolveBeforeInstantiation()
是用来触发我们预埋的实例化之前的扩展点的:
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
*/
@Nullable
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;
}
可以看到,这边是把实例化->初始化当成原子操作的,即:如果已经实例化,那么就直接执行初始化之后的回调,否则执行实例化之前的回调。
Spring预留的扩展点我们点到为止,还是主要来看下Bean实例化的过程.
/**
* 实际创建Bean实例。在执行这个动作之前,postProcessBeforeInstantiation已经被执行过。
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 1 实例化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
synchronized (mbd.postProcessingLock) {
// 合并BeanDefinition信息,如果bean实现了MergedBeanDefinitionPostProcessor接口,会将各种类型的BeanDefinition子类转变为RootBeanDefinition类型。
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
......省略 循环依赖部分
try {
// 2 属性注入
populateBean(beanName, mbd, instanceWrapper);
// 3 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
......省略 循环依赖部分
}
可以看到整个doCreateBean()
逻辑分三步完成:
- 实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
- 属性注入
populateBean(beanName, mbd, instanceWrapper);
- 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
第一步:实例化(Instantiation)
Spring Bean的实例化采用模板方法,实例化步骤为: Supplier获取->工厂方法获取->反射生成
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1 Make sure bean class is actually resolved at this point.
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 2 如果提供了Supplier,通过Supplier产生对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 3 如果提供了工厂方法,则使用工厂方法产生对象,在@Configuration配置的Bean的方法,会被解析为BeanFactoryMethod
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 4 反射生成。推断构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
这里提一下Supplier,它是Java里的一个函数式接口,只有一个抽象方法get(),用于返回一个对象实例。常见的stream.map(Supplier s)入参就是该类型。
第二步: 属性注入(Populate)
本阶段完成了Spring的核心功能之一,依赖注入,在这之前我们需要先了解下什么是依赖注入。
依赖注入(Dependency Injection, DI)是一种设计模式,也是Spring框架的核心概念之一。其作用是去除Java类之间的依赖关系,实现松耦合,以便于开发测试。
例如,A类要依赖B类,依赖有两个方面:
一方面,B不能换成B1,B2等,它会影响可扩展性
另一方面,A要负责对B实例创建销毁。那么B的修改很可能就会影响到A本身。
我们在Spring常用到的@Autowired,为什么只是声明一下就可以直接使用,而不需要引用任何实例。我们在第一步创建好了实例,这一步就是将创建的实例注入到变量的过程。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
......省略
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 1 根据注入类型,自动注入到dependentBeanMap中
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 2 调用BeanPostProcessor,完成@Autowired @Resource属性填充
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
}
}
// 3 依赖检查
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
// 4 将属性应用到Bean中
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
第三步:初始化(Initialize)
该阶段主要是对Bean做初始化操作,包括 回调Aware接口,回调初始化方法,生成代理对象等。
Aware 翻译为“感知”,可以通过实现Aware接口获取容器或者Bean的某些信息,比如常见的:
BeanNameAware: 可以获取容器中bean的名称
BeanFactoryAware:获取当前bean factory这也可以调用容器的服务
ApplicationContextAware:当前的applicationContext,这也可以调用容器的服务
当Bean实现了BeanFactoryAware接口,可以通过重写setBeanFactory()方法获取到当前的BeanFactory信息。
看下初始化代码initializeBean()
方法
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// 1 回调Aware方法,此处主要包含(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware)
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 扩展点 调用postProcessBeforeInitialization()方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 如果Bean的方法添加了@PostConstruct注解,则会在此处调用该方法
// 如果Bean实现了InitializingBean接口,则会在此处调用afterPropertiesSet()方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 扩展点 调用postProcessAfterInitialization()方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
至此,整个Spring的IOC就构建起来了。