Spring 中 Bean 的生命周期

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 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 的创建和销毁逻辑。

目录
相关文章
|
21天前
|
XML 安全 Java
|
3天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
22 6
|
5天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
35 3
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
19天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
28 1
|
2月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
80 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
3月前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
318 24
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
2月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
3月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
250 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
3月前
|
XML Java 数据格式
spring复习02,xml配置管理bean
详细讲解了Spring框架中基于XML配置文件管理bean的各种方式,包括获取bean、依赖注入、特殊值处理、属性赋值、集合类型处理、p命名空间、bean作用域及生命周期和自动装配。
spring复习02,xml配置管理bean