Bean生命周期
在使用Spring时我们将Bean交给Spring容器来管理,换句话来说就是Bean的整个生命周期都交由Spring容器来控制,所以在学习Spring时很有必要对Bean的生命周期有所了解。
Bean的生命周期有很多个过程,但是这里我不准备按照常规的流程来细说,而是先介绍四个主要过程,然后再在主要过程中查询生命周期的其他过程。这样有利于我们学习和记忆,分析起来也会更加清晰。总体来说Bean的生命周期可以分为四个主要过程:实例化、属性赋值、初始化、销毁。
对于Bean生命周期的分析,我们可以从BeanFactory的getBean方法入手,该方法内部实现方法为「doGetBean」。跟随源码分析,方法调用链如下:「AbstractBeanFactory#doGetBean」->「AbstractAutowireCapableBeanFactory#createBean」->「AbstractAutowireCapableBeanFactory#doCreateBean」,Bean的生命周期的前三个主要阶段都在该方法中有体现,我们后续的源码主要分析大致就在这一块。
AbstractAutowireCapableBeanFactory#doCreateBean
该方法的注释上有说,这个方法就是实际创建指定Bean的方法。这个方法内部很复杂,但是我们主要研究这个方法中涉及的Bean生命周期中的前三个阶段,在该方法中分别对应的方法名为:「createBeanInstance」、「populateBean」、「initializeBean」,这个三个方法分别对应的就是实例化、属性赋值、初始化。
实例化
实例化就是根据提供的信息创建出一个实例对象,你可以简单的理解成我们平时写代码时「new」一个对象。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 确保真正的解析了Bean的类型
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//判断是否可以通过Supplier获取Bean实例
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//静态工厂或者实例工厂
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//如果之前创建过该类型的Bean,在此做一个优化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
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);
}
//上一步没有找到则使用首选的构造函数
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
//使用无参构造函数
return instantiateBean(beanName, mbd);
}
通过上面的源码我们可以确定实例化的主要过程:
-
首先是确保Bean的类型解析出来,在 AbstractBeanDefinition
中有一个属性beanClass
就是用来存储类型的。该类型并不是你认为的Class类型,而是一个Object类型,你一定很好奇为什么是Object类型。BeanDefinition中存储的beanClass它的只是Class的全称类型就是String,后来经过解析才将字符串类型的类型名称转化成Class类型,这一步就是调用的resolveBeanClass
。 -
接着就是通过判断是否可以通过 Supplier
或者工厂方法获取实例。对于工厂方法创建Bean实例这个我们不陌生,但对于Supplier可能会有点不太明白。不管是静态工厂还是实例工厂方法,最后都需要反射来调用目标方法,反射或多或少的对性能都会有影响。在Java中提供了函数式接口编程,对于Supplier
它只有一个方法,通过该方法回调来获取实例。
//创建IOC容器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//创建BeanDefinition
AbstractBeanDefinition personBd = BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.addPropertyValue("name", "jack")
.addPropertyValue("age", 19)
.getBeanDefinition();
personBd.setInstanceSupplier((Supplier<Person>) () -> {
System.out.println("调用Supplier创建实例");
return new Person();
});
//注册BeanDefinition
factory.registerBeanDefinition("jack",personBd);
//获取实例
Person jack = factory.getBean("jack", Person.class);
System.out.println(jack);
最后的运行结果如下:
调用Supplier创建实例
Person(name=jack, age=19)
-
接下来这部分代码只是一个优化代码。如果这个类型之前创建过,有部分信息就不需要重新再解析一遍,而是使用之前解析过的数据就行。 -
下面就到了自动装配候选构造函数了。这里面有一个方法 determineConstructorsFromBeanPostProcessors
,通过方法名称我们也能知道这个是用来确定构造函数的,它是通过什么方式来确定呢?从名字也能知道它是通过BeanPostProcessor来确定的(BeanPostProcessor很重要,本文只会简单的讲一下后续会出相关文章详解)。如果此时BeanPostProcessor有返回构造函数、Bean的自动装配为AUTOWIRE_CONSTRUCTOR
、含有构造参数等情形中的一种,此时就会使用自动装配构造函数的方式来实例化。 -
如果上面的方式还是不行,就下来就会尝试通过首选构造函数创建。 -
最后上面的方式都不行,最后就会使用 instantiateBean
来实例化,其实就是使用默认的无参构造函数来实例化Bean。这个方法内部是怎样实例化Bean的呢?在该方法内部有依据关键性代码:
beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
这里面的getInstantiationStrategy
会返回一个InstantiationStrategy
,从名字可以看出这就是一个实例化策略。这是Spring定义的一个实例化策略接口,在Spring中有两个实现分别为SimpleInstantiationStrategy
和CglibSubclassingInstantiationStrategy
,默认情况下使用的是CglibSubclassingInstantiationStrategy
也就是CGLIB的方式。关于具体详情这里就不展开细讲,有兴趣的可以自己去了解。
在instantiateBean
最后它会将创建完的Bean实例包装成一个BeanWrapper返回,BeanWrapper是个什么东西呢?简单的说就是它是Spring提供的一个用来操作JavaBean的工具,通过它可以更方便就行属性值的转换、嵌套属性设置等等。
属性赋值
继续分析doCreateBean
方法,接下来可以看见populateBean(beanName, mbd, instanceWrapper)
方法,该方法就是属性赋值。对于属性赋值,简单的说就是将BeanDefinition中设置定属性值赋值到实例中去的一个过程。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
//没有实例化对象
if (bw == null) {
//有属性执行抛出异常
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// 跳过属性赋值过程
return;
}
}
//在设置属性之前给InstantiationAwareBeanPostProcessors最后一次改变bean的机会
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// 如果为InstantiationAwareBeanPostProcessors
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//postProcessAfterInstantiation:如果应该在bean上面设置属性,则返回true,否则返回false
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
//自动装配
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 根据属性名称自动装配
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 根据类型自动装配
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//判断是否注册了InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
//判断是否要依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
//处理InstantiationAwareBeanPostProcessor
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
//依赖检查
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
//将属性应用到Bean中
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
上面整个代码中的主要要干的事就是将BeanDefinition中的属性值赋值给BeanWrapper对象,同时还有一个重要的点就是在属性赋值的过程中会有处理BeanPostProcessor的逻辑。
初始化
继续分析doCreateBean
方法,接下来可以看见initializeBean(beanName, exposedObject, mbd)
方法,该方法就是初始化。那么初始化会做哪些事情呢?
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
//执行invokeAwareMethods
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//应用BeanPostProcessor的postProcessBeforeInitialization方法
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行invokeInitMethods
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()) {
//应用BeanPostProcessor的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
上面就是整个初始化的过程,上面的代码还是比较清晰的,里面有几个方法我们需要深入了解一下。首先就是这里面的invokeAwareMethods
,这个方法的内部实现如下:
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
这个方法有什么用呢?在Spring中有一大堆的Aware接口,这个接口的作用就是Spring帮你注入你想要的对象。我们直接上代码:
public class LifecycleDemo1 {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("spring-life-cycle-1.xml");
Object mac = factory.getBean("mac");
AbstractBeanDefinition personBd = BeanDefinitionBuilder.genericBeanDefinition(Person.class)
.addPropertyValue("name", "jack")
.addPropertyValue("age", 19)
.getBeanDefinition();
personBd.setInstanceSupplier((Supplier<Person>) () -> {
System.out.println("调用Supplier创建实例");
return new Person();
});
factory.registerBeanDefinition("jack",personBd);
Person jack = factory.getBean("jack", Person.class);
System.out.println(jack);
System.out.println("jack.getBeanFactory() == factory : " + (jack.getBeanFactory() == factory));
}
}
@Data
class Person implements BeanFactoryAware {
private String name;
private Integer age;
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
上面示例代码中Person实现接口BeanFactoryAware,然后通过setBeanFactory方法将BeanFactory设置到Person实例中,这样我们就可以在Person实例中获取到BeanFactory,这个BeanFactory就是我们前面手动创建的BeanFactory,从最后的运行结果也可以看出。这个功能的实现就是通过上面的invokeAwareMethods
实现的,如果我们的Bean可以是XXXAware类型,那么它就会回调setXXX接口,然后将XXX设置到我们的Bean中。当然这个只是部分Aware接口,在ApplicationContext中可以实现更丰富的注入。
接下来就是两个applyBeanPostProcessorsXXX
方法,这两个方法主要是一些扩展,这里不展开说持续关注我后续文章会专门拿一期来讲BeanPostProcessor内容。最后就是invokeInitMethods
方法了,这个方法作用是什么呢?直接看源码:
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//判断是不是InitializingBean,如果是则应用
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//应用initMethod
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);
}
}
}
上面方法主要就是用来实现InitializingBean接口和initMethod方法的。通常在Spring中我们可以通过实现InitializingBean
接口或者在BeanDefinition中指定initMethod
方法来实现Bean的初始化,而invokeInitMethods
方法就是Spring实现初始化的实现。下面直接看示例:
-
spring-life-cycle-2.xml配置文件
<bean id="mac" class="com.buydeem.share.lifecycle.User" init-method="initMethod"/>
-
Java代码
public class LifecycleDemo2 {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("spring-life-cycle-2.xml");
User mac = factory.getBean("mac", User.class);
}
}
class User implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean#afterPropertiesSet()方法");
}
public void initMethod(){
System.out.println("自定义initMethod()方法");
}
}
最后的运行结果如下:
调用InitializingBean#afterPropertiesSet()方法
自定义initMethod()方法
从源码和打印结果也可以看出,InitializingBean是会在init-method方法之前生效的。在Spring中我们还可以通过@PostConstruct
来指定初始化方法,对于@PostConstruct
它并不是Spring的而是在java的JSR-250中的一个注解,只不过Spring对JSR-250中的注解有部分支持而已。那么这个是如何实现的呢?这个功能其实Spring是通过BeanPostProcessor来实现的,在前面有一个方法叫applyBeanPostProcessorsBeforeInitialization
,而@PostConstruct
就是通过该方法实现的,具体实现逻辑在InitDestroyAnnotationBeanPostProcessor
可以找到,这个在将在BeanPostProcessor中细讲。修改前面示例的Java代码如下:
public class LifecycleDemo2 {
public static void main(String[] args) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions("spring-life-cycle-2.xml");
//可以使用 new CommonAnnotationBeanPostProcessor()替换
InitDestroyAnnotationBeanPostProcessor postProcessor = new InitDestroyAnnotationBeanPostProcessor();
postProcessor.setInitAnnotationType(PostConstruct.class);
factory.addBeanPostProcessor(postProcessor);
User mac = factory.getBean("mac", User.class);
}
}
class User implements InitializingBean {
@PostConstruct
public void postConstruct(){
System.out.println("@PostConstruct");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean#afterPropertiesSet()方法");
}
public void initMethod(){
System.out.println("自定义initMethod()方法");
}
}
结合源码可以知道初始化的顺序是@PostConstruct->InitializingBean接口->BeanDefinition中的initMethod方法
。
销毁
前面Bean的生命周期中前三个我们可以在doCreateBean
方法中找到,对于最后的销毁阶段我们可以通过BeanFactory中destroyBean
找到对应的源码。
public void destroy() {
//处理BeanPostProcessor扩展并应用postProcessBeforeDestruction方法
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
//如果实现DisposableBean接口则调用其destroy方法
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
//调用BeanDefinition中定义的destroyMethod方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
对于Bean的销毁主要流程对比Bean的初始化过程有很多相似之处。在Spring中我们通常可以通过三种方式来自定义Bean的销毁扩展,分别是使用@PreDestroy
注解方法、实现DisposableBean
接口、在BeanDefinition中定义destroyMethod
。废话不多说直接看示例:
-
spring-life-cycle-3.xml配置文件
<bean id="userService" class="com.buydeem.share.lifecycle.UserService" destroy-method="destroyMethod"/>
-
java示例代码
public class LifeCycleDemo3 {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("spring-life-cycle-3.xml");
//注册BeanPostProcessor
InitDestroyAnnotationBeanPostProcessor beanPostProcessor = new InitDestroyAnnotationBeanPostProcessor();
beanPostProcessor.setInitAnnotationType(PostConstruct.class);
beanPostProcessor.setDestroyAnnotationType(PreDestroy.class);
beanFactory.addBeanPostProcessor(beanPostProcessor);
UserService userService = beanFactory.getBean("userService", UserService.class);
beanFactory.destroyBean("userService",userService);
}
}
class UserService implements DisposableBean {
@PreDestroy
public void preDestroy(){
System.out.println("执行@PreDestroy方法");
}
public void destroy() throws Exception {
System.out.println("执行DisposableBean#destroy()方法");
}
public void destroyMethod(){
System.out.println("执行自定义destroyMethod()方法");
}
}
-
运行结果
执行@PreDestroy方法
执行DisposableBean#destroy()方法
执行自定义destroyMethod()方法
从运行结果可以看出,它们的顺序分别是@PreDestroy ->DisposableBean->destroyMethod
。其中@PreDestroy
它与@PostConstruct
一样都是Spring对JSR-250的支持,它们都是通过BeanPostProcessor实现的。
小结
本文并未将Bean的整个生命周期全部讲完,特别是对于BeanPostProcessor部分并未做详细说明。看完该文我们需要知道以下几点:
-
Bean的主要生命周期就是实例化、属性赋值、初始化、销毁。 -
对于Bean的每个主要生命周期中的大致流程。 -
在主要的生命周期中间穿插了许多BeanPostProcessor扩展。 -
对于初始化时,我们可以通过@PostConstruct注解、InitializingBean接口和BeanDefinition中定义初始化方法来实现自定义初始化,以及这三种方式的执行顺序。 -
对于销毁时,我们可以通过@PreDestroy注解、DisposableBean接口和BeanPostProcessor中定义销毁方法实现自定义销毁,以及这三种方式的执行顺序。
对于Bean的生命周期这只是开篇的文章,在后面我准备再出一期将BeanPostProcessor相关内容的文章,最后再通过一篇文章来丰富整个Bean的生命周期。欢迎关注微信公众号,及时关注后续更新内容。
原文始发于微信公众号(一只菜鸟程序员):Spring进阶-Bean生命周期(上)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/73000.html