程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Spring

    • Spring6 - 概述
    • Spring6 - 入门
    • Spring6 - IOC(基于XML)
    • Spring6 - IOC(基于注解)
    • spring6 - FactoryBean
    • Spring6 - Bean的作用域
    • Spring6 - Bean生命周期
      • Bean 的生命周期五步
      • Bean 生命周期七步:比五步添加的那两步在哪里?在初始化 Bean 的前和后。
      • Bean 生命周期十步:比七步添加的那三步在哪里?
      • Bean 生命周期详细解释
        • 1. Bean 定义的注册
        • 2. Bean 的实例化
        • 3. 设置 Bean 属性
        • 4. 实现各种 Aware 接口
        • 5. BeanPostProcessor 的前置处理
        • 6. InitializingBean 和自定义初始化方法
        • 7. BeanPostProcessor 的后置处理
        • 8. 使用 Bean
        • 9. DisposableBean 和自定义销毁方法
        • 10. 容器关闭
        • 其他接口和功能
      • Bean 生命周期代码演示
        • 1. 创建一个简单的 Bean 类
        • 2. 配置 Bean 和 BeanPostProcessor
        • 方式1:配置类实现
        • 方式2:XML实现
        • 3. 运行并观察生命周期
      • ⾃⼰new的对象如何让Spring管理
        • 1. 使用 @Configurable 注解
        • 2. 手动注册对象到 Spring 上下文
        • 3. 使用 @Bean 注解的方法
    • Spring6 - Bean循环依赖
    • Spring6 - 手写IOC容器
    • Spring6 - AOP
    • Spring6 - 自定义注解
    • Spring6 - Junit
    • Spring6 - 事务
    • Spring6 - Resource
    • Spring6 - 国际化
    • Spring6 - 数据校验
    • Spring6 - Cache
    • Spring集成Swagger2
  • Spring生态
  • Spring
scholar
2024-04-09
目录

Spring6 - Bean生命周期

1712611719366

# Bean 的生命周期五步

  1. 实例化 Bean:创建 Bean 的实例。
  2. Bean 属性赋值:为 Bean 注入属性和依赖。
  3. 初始化 Bean:执行自定义初始化方法或 @PostConstruct 注解方法。
  4. 使用 Bean:Bean 已准备好,可以被应用使用。
  5. 销毁 Bean:当应用或容器关闭时,执行销毁方法或 @PreDestroy 注解方法。

# Bean 生命周期七步:比五步添加的那两步在哪里?在初始化 Bean 的前和后。

  1. 实例化 Bean
  2. Bean 属性赋值
  3. 执行“Bean 后置处理器”的 before 方法:BeanPostProcessor 的 postProcessBeforeInitialization 方法执行。
  4. 初始化 Bean
  5. 执行“Bean 后置处理器”的 after 方法:BeanPostProcessor 的 postProcessAfterInitialization 方法执行。
  6. 使用 Bean
  7. 销毁 Bean

# Bean 生命周期十步:比七步添加的那三步在哪里?

  • 点位1:在“Bean 后置处理器”before方法之前
    • 干了什么事儿?
      • 检查 Bean 是否实现了 Aware 相关的接口,如果实现了接口则调用这些接口中的方法。然后调用这些方法的目的是为了给你传递一些数据,让你更加方便使用。
  • 点位2:在“Bean 后置处理器”before方法之后
    • 干了什么事儿?
      • 检查 Bean 是否实现了 InitializingBean 接口,如果实现了,则调用接口中的方法。
  • 点位3:使用 Bean 之后,或者说销毁 Bean 之前
    • 干了什么事儿?
      • 检查 Bean 是否实现了 DisposableBean 接口,如果实现了,则调用接口中的方法。

添加的这三个点位的特点:都是在检查你这个 Bean 是否实现了某些特定的接口,如果实现了这些接口,则 Spring 容器会调用这个接口中的方法。

# Bean 生命周期详细解释

Spring Bean 的生命周期是相对复杂的,因为它包含了多个阶段和回调接口,这使得开发者可以在 Bean 的生命周期的不同阶段插入自定义逻辑。下面是对每个阶段更详细的解释:

# 1. Bean 定义的注册

Spring 容器在启动时会首先加载并注册 Bean 的定义信息。这些定义信息可以来自于多个来源,包括 XML 配置文件、Java 配置类、注解等。在这个阶段,容器不会创建 Bean 的实例,只是将其定义信息(包括类类型、作用域、生命周期回调等)读入并进行注册。

# 2. Bean 的实例化

根据 Bean 的定义信息,Spring 容器会通过反射等机制创建 Bean 的实例。这个过程主要发生在两种类型的 Bean 之间:使用默认构造函数创建的 Bean,以及通过工厂方法创建的 Bean。如果 Bean 配置了懒加载(Lazy-Init),这个步骤会被延迟到首次获取 Bean 时进行。

提示

实例化指的是通过调用构造方法为对象在堆内存中分配空间的过程。此时,对象已经被创建,但是它的状态可能还不完整,因为它的属性可能还没有被设置。

在 Spring 中,Bean 的实例化可以通过几种方式进行:

1. 默认构造函数

当一个 Bean 定义没有指定工厂方法或构造函数参数时,Spring 会使用类的默认(无参)构造函数来创建 Bean 实例。这是最直接和常见的实例化方式。例如:

public class MyBean {
    public MyBean() {
        // 默认构造函数
    }
}
1
2
3
4
5

2. 工厂方法

Spring 允许使用静态工厂方法或者工厂 Bean 的非静态方法来创建 Bean 实例。这种方式在创建对象时提供了更高的灵活性,特别是对于那些没有无参构造函数的类,或者在创建对象时需要执行额外逻辑的情况。

静态工厂方法:

public class MyBeanFactory {
    public static MyBean createInstance() {
        // 执行一些额外的逻辑
        return new MyBean();
    }
}
1
2
3
4
5
6

工厂 Bean 的方法:

public class MyBeanFactory {
    public MyBean createInstance() {
        // 执行一些额外的逻辑
        return new MyBean();
    }
}
1
2
3
4
5
6

3. 懒加载(Lazy-Init)

默认情况下,Spring 容器在启动时会创建和配置所有单例范围的 Bean。但是,你可以配置一个 Bean 为懒加载(lazy-init),这意味着该 Bean 在首次被请求时才会被创建和初始化,而不是在应用启动时。这样做可以减少应用启动时间,特别是对于大型应用来说非常有用。

懒加载的配置示例:

<bean id="myLazyBean" class="com.example.MyBean" lazy-init="true"/>
1

或者使用注解方式:

@Bean(lazyInit = true)
public MyBean myLazyBean() {
    return new MyBean();
}
1
2
3
4

# 3. 设置 Bean 属性

创建 Bean 实例之后,Spring 容器会根据 Bean 定义信息中的属性声明,通过反射机制来注入属性。这包括对其他 Bean 的引用、基本类型值的注入等。

提示

在 Spring 框架中,设置 Bean 属性的几种主要方式包括直接在 XML 配置文件中使用 <property> 元素指定属性值,通过 Java 配置类中的 @Bean 方法配合构造器注入或设置器方法注入属性值,以及利用 @Autowired 注解实现自动装配,自动装配可以应用于字段、构造器、设置器方法,从而减少显式配置的需要,提高开发效率和代码的灵活性。

# 4. 实现各种 Aware 接口

Spring 容器提供了一系列的 Aware 接口,让 Bean 可以感知到容器的某些特定功能。BeanNameAware、BeanFactoryAware 和 ApplicationContextAware 是其中最常用的几个。实现了这些接口的 Bean 在属性填充之后,会收到相应的回调,例如,一个 Bean 可以通过 BeanNameAware 获知自己在容器中的名称。

BeanNameAware

  • 用途:允许一个 Bean 获知自己在 Spring 容器中的名称(或 ID)。
  • 方法:void setBeanName(String name)
  • 场景:当你希望基于 Bean 的名称来执行特定逻辑,或者仅仅是为了记录目的,实现此接口会非常有用。

BeanFactoryAware

  • 用途:允许一个 Bean 访问持有它的 Spring BeanFactory,即 Spring IoC 容器。
  • 方法:void setBeanFactory(BeanFactory beanFactory)
  • 场景:如果你需要访问 Spring 容器,以获取其他 Bean 或查询容器的状态,实现此接口会很有帮助。它特别适用于需要大量操作 Spring 容器的 Bean。

ApplicationContextAware

  • 用途:比 BeanFactoryAware 提供了更丰富的功能。允许访问当前的 ApplicationContext,从而让 Bean 能够访问应用级别的上下文环境,例如文件资源、发布事件等。
  • 方法:void setApplicationContext(ApplicationContext applicationContext)
  • 场景:当你的 Bean 需要访问资源文件、发布应用事件或需要访问应用上下文的其他特定功能时,实现此接口很有用。

# 5. BeanPostProcessor 的前置处理

在 Bean 初始化之前,Spring 容器会调用所有注册的 BeanPostProcessor 的 postProcessBeforeInitialization 方法。这给了开发者一个机会在 Bean 属性设置完毕后、初始化前进行自定义逻辑处理。

# 6. InitializingBean 和自定义初始化方法

如果 Bean 实现了 InitializingBean 接口,容器会在所有属性设置之后调用 afterPropertiesSet() 方法。此外,如果 Bean 定义中指定了 init-method,该方法也会在 afterPropertiesSet() 之后被调用。

# 7. BeanPostProcessor 的后置处理

Bean 初始化完成之后,容器会调用所有注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法。这是对 Bean 进行最后修改的机会。

# 8. 使用 Bean

此时,Bean 已经完全初始化,可以被应用程序使用。

# 9. DisposableBean 和自定义销毁方法

当容器关闭时,如果 Bean 实现了 DisposableBean 接口,容器会调用 destroy() 方法。此外,如果 Bean 定义中指定了 destroy-method,该方法也会被调用。这些方法提供了一个回调,允许 Bean 在容器关闭前进行必要的资源清理工作。

# 10. 容器关闭

这是 Bean 生命周期的最后阶段。Spring 容器会在关闭时逐个销毁单例模式的 Bean,按照依赖关系逆序执行销毁逻辑,确保依赖项在被依赖项之前销毁。

# 其他接口和功能

  • 工厂方法与 FactoryBean:对于那些需要复杂创建逻辑的 Bean,可以通过实现 FactoryBean 接口或使用工厂方法来创建。
  • 作用域:Spring 支持不同的 Bean 作用域,例如单例(Singleton)、原型(Prototype)、会话(Session)等,这会影响 Bean 的生命周期和管理方式。
  • 生命周期注解:Spring 还支持通过 @PostConstruct 和 @PreDestroy 注解来标注初始化和销毁方法,这为 Bean 生命周期管理提供了更灵活的方式。

# Bean 生命周期代码演示

# 1. 创建一个简单的 Bean 类

首先,我们定义一个名为 LifeCycleBean 的 Java 类,这个类会展示 Spring Bean 生命周期的关键阶段:

package com.example.lifecycle;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class LifeCycleBean implements InitializingBean, DisposableBean, ApplicationContextAware, BeanNameAware {

    private String value;

    // 构造函数 - 在Bean的创建过程中最先被调用,用于实例化Bean。
    public LifeCycleBean() {
        System.out.println("1. Bean 实例化");
    }

    // Spring依赖注入 - 通过反射机制将属性值注入到Bean的属性中。
    public void setValue(String value) {
        System.out.println("2. 属性值注入");
        this.value = value;
    }

    // BeanNameAware接口 - 用于获取Bean的ID或名称,Spring容器会在Bean的属性设置完成后调用此方法。
    @Override
    public void setBeanName(String name) {
        System.out.println("3. BeanNameAware接口方法调用,Bean 名称为: " + name);
    }

    // ApplicationContextAware接口 - 允许Bean获取Spring ApplicationContext,从而让Bean能够使用容器的服务。
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        System.out.println("4. ApplicationContextAware接口方法调用");
    }

    // @PostConstruct注解 - 标记自定义初始化方法,此方法在Bean的属性设置完成并且满足所有Bean的依赖之后被调用。
    @PostConstruct
    public void initMethod() {
        System.out.println("5. @PostConstruct注解定义的自定义初始化方法");
    }

    // InitializingBean接口 - afterPropertiesSet方法在所有Bean的属性被设置后调用,也就是在@PostConstruct注解方法之后被调用。
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("6. InitializingBean接口方法调用--重写afterPropertiesSet方法进行初始化");
    }

    // 自定义初始化方法 - 可以在配置文件中通过init-method属性指定,也在Java配置中通过@Bean(initMethod="")指定。
    public void customInitMethod() {
        System.out.println("7. XML配置或Java配置中init-method属性定义的自定义初始化方法");
    }

    // @PreDestroy注解 - 标记自定义销毁方法,此方法在Bean销毁之前被调用,用于资源清理等。
    @PreDestroy
    public void preDestroy() {
        System.out.println("8. @PreDestroy注解定义的自定义销毁方法");
    }

    // DisposableBean接口 - destroy方法在Bean销毁时调用,用于释放资源,这个方法在@PreDestroy注解方法之后调用。
    @Override
    public void destroy() throws Exception {
        System.out.println("9. DisposableBean接口方法调用 -- 重写destroy方法自定义销毁逻辑");
    }

    // 自定义销毁方法 - 可以在配置文件中通过destroy-method属性指定,也在Java配置中通过@Bean(destroyMethod="")指定。
    public void customDestroyMethod() {
        System.out.println("10. XML配置或Java配置中destroy-method属性定义的自定义销毁方法");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  • 构造函数和属性注入发生在Bean实例化的初期阶段。
  • BeanNameAware 和 ApplicationContextAware 提供了一种机制,让 Bean 在实例化过程中能够访问到容器的一些环境信息。
  • @PostConstruct 和 InitializingBean 的 afterPropertiesSet 方法都用于初始化过程,但 @PostConstruct 优先于 afterPropertiesSet 执行。
  • @PreDestroy 和 DisposableBean 的 destroy 方法都用于销毁过程,@PreDestroy 优先于 destroy 执行。
  • 通过 XML 或 Java 配置指定的自定义初始化和销毁方法提供了更多的灵活性,允许在不修改Bean源代码的情况下,改变初始化和销毁的行为。

# 2. 配置 Bean 和 BeanPostProcessor

# 方式1:配置类实现

我们将通过 Java 配置类来定义 Bean 和 BeanPostProcessor。这个配置类注册了 LifeCycleBean 和自定义的 BeanPostProcessor,以便在 Bean 的初始化之前和之后执行一些自定义逻辑。

package com.example.lifecycle;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    // 定义一个Bean,同时指定了自定义的初始化方法和销毁方法
    @Bean(initMethod = "customInitMethod", destroyMethod = "customDestroyMethod")
    public LifeCycleBean lifeCycleBean() {
        // 返回LifeCycleBean的一个实例
        return new LifeCycleBean();
    }

    // 定义一个自定义的BeanPostProcessor Bean,用于在Bean的初始化前后执行自定义逻辑
    @Bean
    public BeanPostProcessor customBeanPostProcessor() {
        // 创建匿名内部类的实例
        return new BeanPostProcessor() {
            // 在Bean初始化之前调用
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) {
                // 检查当前bean是否是LifeCycleBean的实例
                if (bean instanceof LifeCycleBean) {
                    // 如果是,则输出信息
                    System.out.println("5.1 BeanPostProcessor接口的postProcessBeforeInitialization方法调用");
                }
                // 返回处理过的bean实例
                return bean;
            }

            // 在Bean初始化之后调用
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) {
                // 检查当前bean是否是LifeCycleBean的实例
                if (bean instanceof LifeCycleBean) {
                    // 如果是,则输出信息
                    System.out.println("7.1 BeanPostProcessor接口的postProcessAfterInitialization方法调用");
                }
                // 返回处理过的bean实例
                return bean;
            }
        };
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 方式2:XML实现

使用 XML 配置来定义 Bean、自定义初始化和销毁方法,以及实现 BeanPostProcessor,我们首先需要创建相应的 Java 类,然后在 XML 文件中进行配置。

1. 创建自定义 BeanPostProcessor 实现

package com.example.lifecycle;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class CustomBeanPostProcessor implements BeanPostProcessor {

    @Override // 在Bean初始化之前调用该方法
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 如果当前正在初始化的Bean是LifeCycleBean实例
        if (bean instanceof LifeCycleBean) {
            // 执行自定义逻辑
            System.out.println("BeanPostProcessor 的 postProcessBeforeInitialization 方法调用");
        }
        // 返回传入的Bean
        return bean;
    }

    @Override  // 在Bean初始化之后调用该方法
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 同样,检查Bean实例
        if (bean instanceof LifeCycleBean) {
            // 执行自定义逻辑
            System.out.println("BeanPostProcessor 的 postProcessAfterInitialization 方法调用");
        }
        // 返回Bean实例
        return bean;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

BeanPostProcessor 提供了两个回调方法,允许在 Bean 初始化的前后执行自定义逻辑:

  • postProcessBeforeInitialization:此方法在任何 Bean 初始化回调(如设置属性后、自定义初始化方法或 @PostConstruct 注解方法之前)之前被调用。可以用来对 Bean 进行预处理,例如修改 Bean 的属性。需要注意的是,如果这个方法返回了一个不同于传入的 Bean 实例,那么新的 Bean 实例将会替换原本的 Bean 实例继续进行生命周期的后续处理。
  • postProcessAfterInitialization:此方法在 Bean 初始化之后被调用,即在初始化回调(如自定义初始化方法或 @PostConstruct 注解方法之后)之后。这个阶段是在所有初始化工作完成后,可以用来进行后处理,如代理包装。

2. XML 配置文件

在 XML 配置文件中,我们会定义 LifeCycleBean Bean,并指定自定义的初始化和销毁方法。同时,我们也将注册自定义的 BeanPostProcessor。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 定义 LifeCycleBean 并指定自定义的初始化和销毁方法-->
    <bean id="lifeCycleBean" class="com.example.lifecycle.LifeCycleBean"
          init-method="customInitMethod" destroy-method="customDestroyMethod">
    </bean>

    <!-- 注册 BeanPostProcessor -->
    <bean class="com.example.lifecycle.CustomBeanPostProcessor"></bean>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3. 运行并观察生命周期

最后,创建一个主类来启动 Spring 应用上下文,并观察 LifeCycleBean 生命周期的各个阶段。

package com.example.lifecycle;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println("Spring 容器已启动,现在获取 LifeCycleBean...");
        LifeCycleBean bean = context.getBean(LifeCycleBean.class);
        System.out.println("LifeCycleBean 实例获取完毕。");
        context.close();
        System.out.println("Spring 容器关闭。");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

运行上述程序,将会在控制台看到如下输出(部分输出顺序可能因为 BeanPostProcessor 的配置不同而略有差异):

image-20240409051536577

# ⾃⼰new的对象如何让Spring管理

通常,Spring 管理的 Bean 是由 Spring 容器通过解析配置文件(XML 或 Java Config)自动实例化和初始化的。但有时候,你可能会在应用中通过 new 操作符自己实例化对象,这些对象默认情况下不会被 Spring 管理。不过,有几种方法可以将这些自行实例化的对象纳入 Spring 管理:

# 1. 使用 @Configurable 注解

如果你想让通过 new 操作符创建的对象能够享受 Spring 的依赖注入等特性,可以考虑使用 AspectJ 的织入功能与 @Configurable 注解。这需要在编译时或加载时通过 AspectJ 来增强类,以便 Spring 可以在对象创建时自动注入依赖。

@Configurable
public class MyClass {
    @Autowired
    private MyDependency myDependency;

    // 类的其他部分
}
1
2
3
4
5
6
7

这种方法需要额外的配置和编译步骤,包括在项目中加入 AspectJ 的依赖和配置编译器插件。

# 2. 手动注册对象到 Spring 上下文

另一种方法是在应用的运行时,将通过 new 创建的对象手动注册到 Spring 应用上下文中:

@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
1
2
3
4
5
6
7
8

如果对象已经被创建,可以通过编程方式将其注册到 Spring 上下文中:

@Autowired
private ConfigurableApplicationContext applicationContext;

public void registerBeanDynamically() {
    MyBean myBean = new MyBean();
    applicationContext.getBeanFactory().registerSingleton("myBean", myBean);
}
1
2
3
4
5
6
7

# 3. 使用 @Bean 注解的方法

在配置类中,可以使用 @Bean 注解的方法来创建和注册 Bean。即使方法内部使用 new 来实例化对象,Spring 也会自动管理这些对象,包括执行依赖注入、调用初始化方法等。

@Configuration
public class MyConfig {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
1
2
3
4
5
6
7
8

注意事项

直接使用 new 创建的对象,除非通过上述方法之一注册到 Spring 上下文中,否则它们不会享受到 Spring 提供的特性,如依赖注入、生命周期管理等。尽可能使用 Spring 的机制来创建和管理 Bean,以保持应用的一致性和可维护性。

编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Spring6 - Bean的作用域
Spring6 - Bean循环依赖

← Spring6 - Bean的作用域 Spring6 - Bean循环依赖→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式