解析Spring中Bean的生命周期

简介: 解析Spring中Bean的生命周期

解析Spring框架中Bean的生命周期不仅可以帮助我们更好地理解Spring的工作机制,还能让我们在实际开发中更加得心应手。Spring管理Bean的生命周期涉及多个步骤,从实例化到销毁,每一个步骤都有其独特的处理逻辑。本文将通过源码详细解析Spring中Bean的生命周期。

 

1. Bean的生命周期概述

 

Spring中Bean的生命周期包括以下几个主要阶段:

 

1. **实例化(Instantiation)**:创建Bean实例。

2. **属性填充(Populate properties)**:将依赖注入到Bean实例中。

3. **初始化(Initialization)**:调用初始化方法。

4. **使用(Usage)**:Bean处于就绪状态,供应用程序使用。

5. **销毁(Destruction)**:容器关闭时调用销毁方法。

 

这些阶段由不同的组件和机制来共同完成,如`BeanFactory`,`BeanPostProcessor`,以及各种回调接口等。

 

2. 实例化Bean

 

实例化过程由`AbstractAutowireCapableBeanFactory`类的`createBeanInstance`方法负责。它根据Bean定义信息选择合适的构造函数或工厂方法来创建Bean实例。

 

```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);
}
```

 

该方法首先检查Bean定义中是否指定了工厂方法,如果有则通过工厂方法创建Bean实例;否则,尝试使用默认构造函数或带参数的构造函数。

 

3. 属性填充

 

一旦Bean实例创建完成,Spring会将依赖注入到该实例中。这一步由`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`方法,对Bean实例进行后续处理,接着根据自动装配模式(byName或byType)进行依赖注入,最后将属性值应用到Bean实例。

 

4. 初始化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`方法。

 

5. 销毁Bean

 

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

 

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

 

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

 

总结

 

通过对Spring源码的详细分析,我们可以看到Spring是如何管理Bean的生命周期的:

 

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

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

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

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

 

这种设计使得Spring能够灵活地管理Bean的生命周期,并提供了丰富的扩展点供开发者自定义Bean的创建和销毁逻辑。通过了解这些底层机制,我们可以更好地使用和扩展Spring框架,满足复杂应用的需求。

目录
相关文章
|
2月前
|
数据采集 人工智能 Java
1天消化完Spring全家桶文档!DevDocs:一键深度解析开发文档,自动发现子URL并建立图谱
DevDocs是一款基于智能爬虫技术的开源工具,支持1-5层深度网站结构解析,能将技术文档处理时间从数周缩短至几小时,并提供Markdown/JSON格式输出与AI工具无缝集成。
130 1
1天消化完Spring全家桶文档!DevDocs:一键深度解析开发文档,自动发现子URL并建立图谱
|
2月前
|
安全 Java API
深入解析 Spring Security 配置中的 CSRF 启用与 requestMatchers 报错问题
本文深入解析了Spring Security配置中CSRF启用与`requestMatchers`报错的常见问题。针对CSRF,指出默认已启用,无需调用`enable()`,只需移除`disable()`即可恢复。对于`requestMatchers`多路径匹配报错,分析了Spring Security 6.x中方法签名的变化,并提供了三种解决方案:分次调用、自定义匹配器及降级使用`antMatchers()`。最后提醒开发者关注版本兼容性,确保升级平稳过渡。
215 2
|
3月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
248 1
|
2月前
|
前端开发 安全 Java
Spring Boot 便利店销售系统项目分包设计解析
本文深入解析了基于Spring Boot的便利店销售系统分包设计,通过清晰的分层架构(表现层、业务逻辑层、数据访问层等)和模块化设计,提升了代码的可维护性、复用性和扩展性。具体分包结构包括`controller`、`service`、`repository`、`entity`、`dto`、`config`和`util`等模块,职责分明,便于团队协作与功能迭代。该设计为复杂企业级应用开发提供了实践参考。
107 0
|
29天前
|
安全 Java API
Spring Boot 功能模块全解析:构建现代Java应用的技术图谱
Spring Boot不是一个单一的工具,而是一个由众多功能模块组成的生态系统。这些模块可以根据应用需求灵活组合,构建从简单的REST API到复杂的微服务系统,再到现代的AI驱动应用。
244 8
|
2月前
|
Java 关系型数据库 MySQL
深入解析 @Transactional——Spring 事务管理的核心
本文深入解析了 Spring Boot 中 `@Transactional` 的工作机制、常见陷阱及最佳实践。作为事务管理的核心注解,`@Transactional` 确保数据库操作的原子性,避免数据不一致问题。文章通过示例讲解了其基本用法、默认回滚规则(仅未捕获的运行时异常触发回滚)、因 `try-catch` 或方法访问修饰符不当导致失效的情况,以及数据库引擎对事务的支持要求。最后总结了使用 `@Transactional` 的五大最佳实践,帮助开发者规避常见问题,提升项目稳定性与可靠性。
307 12
|
2月前
|
缓存 安全 Java
深入解析HTTP请求方法:Spring Boot实战与最佳实践
这篇博客结合了HTTP规范、Spring Boot实现和实际工程经验,通过代码示例、对比表格和架构图等方式,系统性地讲解了不同HTTP方法的应用场景和最佳实践。
208 5
|
2月前
|
安全 Java 数据安全/隐私保护
Spring Security: 深入解析 AuthenticationSuccessHandler
本文深入解析了 Spring Security 中的 `AuthenticationSuccessHandler` 接口,它用于处理用户认证成功后的逻辑。通过实现该接口,开发者可自定义页面跳转、日志记录等功能。文章详细讲解了接口方法参数及使用场景,并提供了一个根据用户角色动态跳转页面的示例。结合 Spring Security 配置,展示了如何注册自定义的成功处理器,帮助开发者灵活应对认证后的多样化需求。
86 2
|
2月前
|
前端开发 IDE Java
Spring MVC 中因导入错误的 Model 类报错问题解析
在 Spring MVC 或 Spring Boot 开发中,若导入错误的 `Model` 类(如 `ch.qos.logback.core.model.Model`),会导致无法解析 `addAttribute` 方法的错误。正确类应为 `org.springframework.ui.Model`。此问题通常因 IDE 自动导入错误类引起。解决方法包括:删除错误导入、添加正确包路径、验证依赖及清理缓存。确保代码中正确使用 Spring 提供的 `Model` 接口以实现前后端数据传递。
91 0
|
3月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
339 29

推荐镜像

更多
  • DNS