Spring 中 Bean 的生命周期

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: Spring 中 Bean 的生命周期

`AbstractAutowireCapableBeanFactory` 是 Spring 框架中负责管理和处理 Bean 生命周期的重要组件。它继承自 `AbstractBeanFactory`,并实现了许多与自动装配和 Bean 创建相关的方法。在深入解析 `AbstractAutowireCapableBeanFactory` 的源码之前,让我们先了解一下 Spring 中 Bean 的生命周期。

 

Spring Bean 的生命周期

 

Spring Bean 的生命周期包括以下几个关键阶段:

1. **实例化**:创建 Bean 的实例。

2. **属性填充**:将依赖对象注入到 Bean 实例中。

3. **初始化**:在 Bean 属性填充完毕后调用初始化方法。

4. **使用**:Bean 准备好被应用程序使用。

5. **销毁**:当容器关闭时,调用 Bean 的销毁方法。

 

AbstractAutowireCapableBeanFactory 概述

 

`AbstractAutowireCapableBeanFactory` 负责管理 Bean 的生命周期,包括实例化、依赖注入、初始化和销毁等过程。下面将通过源码解析来详细解释这些过程。

 

核心代码解析

 

1. 实例化 Bean

 

Spring 使用反射机制来实例化 Bean。在 `AbstractAutowireCapableBeanFactory` 中,实例化过程由 `createBeanInstance` 方法负责。

 

```java
protected Object createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 如果有工厂方法定义,则使用工厂方法创建 Bean 实例
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
 
    // 尝试使用默认构造函数或带参数的构造函数
    Constructor<?> constructorToUse = null;
    synchronized (mbd.constructorArgumentLock) {
        constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
        if (constructorToUse == null) {
            final Class<?> beanClass = resolveBeanClass(mbd, beanName);
            if (beanClass != null) {
                if (!Modifier.isPublic(beanClass.getModifiers())) {
                    throw new BeanCreationException(
                            beanName, "Bean class isn't public, and non-public classes not supported: " + beanClass.getName());
                }
                try {
                    constructorToUse = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
                    mbd.resolvedConstructorOrFactoryMethod = constructorToUse;
                } catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() + "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
                }
            }
        }
    }
    return instantiateBean(beanName, mbd, constructorToUse);
}
```

 

`createBeanInstance` 方法根据 Bean 定义中的信息(如工厂方法、构造函数)来实例化 Bean。如果 Bean 定义中指定了工厂方法,则通过 `instantiateUsingFactoryMethod` 方法来创建 Bean 实例;否则,使用默认构造函数或带参数的构造函数来实例化 Bean。

 

2. 属性填充

 

在实例化 Bean 后,Spring 会将依赖对象注入到 Bean 实例中。这一步由 `populateBean` 方法负责。

 

```java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    beanName, "Cannot apply property values to null instance");
        } else {
            // Skip property population phase for an existing null instance.
            return;
        }
    }
 
    // 应用 InstantiationAwareBeanPostProcessors
    boolean continueWithPropertyPopulation = true;
 
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors(InstantiationAwareBeanPostProcessor.class)) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                continueWithPropertyPopulation = false;
                break;
            }
        }
    }
 
    if (!continueWithPropertyPopulation) {
        return;
    }
 
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
 
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
 
    // 应用 BeanPostProcessors 修改属性值
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
 
    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors(InstantiationAwareBeanPostProcessor.class)) {
                PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (pvs == null) {
                        pvs = mbd.getPropertyValues();
                    }
                    pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
        if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
 
    // 将属性值应用到 Bean 实例
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}
```

 

`populateBean` 方法首先应用 `InstantiationAwareBeanPostProcessor` 接口的 `postProcessAfterInstantiation` 方法,允许在属性填充之前进行一些处理。然后,它根据自动装配模式(byName 或 byType)来处理属性填充,最后将属性值应用到 Bean 实例。

 

3. 初始化 Bean

 

在属性填充完成后,Spring 会调用 Bean 的初始化方法。这一步由 `initializeBean` 方法负责。

 

```java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessControlContext acc = getAccessControlContext();
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, acc);
    } else {
        invokeAwareMethods(beanName, bean);
    }
 
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
 
    try {
        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()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
 
    return wrappedBean;
}
```

 

`initializeBean` 方法首先调用 `invokeAwareMethods` 方法来处理实现了 `Aware` 接口的 Bean。例如,如果 Bean 实现了 `BeanNameAware` 接口,则会调用 `setBeanName` 方法。

 

接下来,方法应用 `BeanPostProcessor` 接口的 `postProcessBeforeInitialization` 方法,然后调用 Bean 的初始化方法(如 `@PostConstruct` 注解的方法或自定义的初始化方法)。最后,应用 `BeanPostProcessor` 接口的 `postProcessAfterInitialization` 方法。

 

4. 销毁 Bean

 

当容器关闭时,Spring 会调用 Bean 的销毁方法。这一步由 `destroyBean` 方法负责。

 

```java
protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware).destroy();
}
```

```java

protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {

   new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessorCache().destructionAware).destroy();

}

```

 

`destroyBean` 方法使用 `DisposableBeanAdapter` 来管理 Bean 的销毁过程。`DisposableBeanAdapter` 会检查 Bean 是否实现了 `DisposableBean` 接口或定义了自定义的销毁方法,并调用相应的销毁方法。

 

总结

 

通过对 `AbstractAutowireCapableBeanFactory` 核心方法的解析,我们可以看到 Spring 是如何管理 Bean 的生命周期的:

 

1. **实例化**:通过反射机制创建 Bean 实例。

2. **属性填充**:将依赖对象注入到 Bean 实例中。

3. **初始化**:在属性填充完毕后调用初始化方法。

4. **销毁**:在容器关闭时调用销毁方法。

 

这种设计使得 Spring 能够灵活地管理 Bean 的生命周期,并提供了丰富的扩展点供开发者自定义 Bean 的创建和销毁逻辑。

目录
相关文章
|
24天前
|
XML Java 数据格式
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
Spring5系列学习文章分享---第一篇(概述+特点+IOC原理+IOC并操作之bean的XML管理操作)
25 1
|
24天前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
27 0
|
1天前
|
XML Java 数据格式
如果在创建Bean的过程中发生异常,Spring会如何处理
如果在创建Bean的过程中发生异常,Spring会如何处理
|
1天前
|
Java Spring 容器
在Spring中,实例化Bean是通过什么方式实现的
在Spring中,实例化Bean是通过什么方式实现的
|
26天前
|
Java Spring 容器
解读spring5源码中实例化单例bean的调用链
解读spring5源码中实例化单例bean的调用链
|
28天前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
28 2
|
17天前
|
Java 微服务 Spring
微服务04---服务远程调用,根据订单id查询订单功能,根据id查询订单的同时,把订单所属的用户信息一起返回,Spring提供了一个工具RestTemplate,Bean写在对象前面,以后可以在任何地
微服务04---服务远程调用,根据订单id查询订单功能,根据id查询订单的同时,把订单所属的用户信息一起返回,Spring提供了一个工具RestTemplate,Bean写在对象前面,以后可以在任何地
|
25天前
|
Java Spring
Spring注解内容----用来替代Bean
Spring注解内容----用来替代Bean
|
25天前
|
Java Linux 程序员
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
技术笔记:Spring生态研习【五】:Springboot中bean的条件注入
|
25天前
|
Java Spring