在 Spring 生态中,Bean 的管理与 SpringBoot 的自动配置是核心基石。理解 Bean 的作用域能合理控制对象创建策略,掌握生命周期可自定义对象行为,而吃透自动配置原理则能清晰 SpringBoot “开箱即用” 的本质。本文将结合实例与源码,系统拆解这三大核心知识点。

一、Bean 的作用域:控制对象的创建策略

Bean 的作用域定义了 Bean 在 Spring 容器中的行为模式,决定了获取 Bean 时是复用实例还是创建新实例,共支持 6 种作用域,其中后 4 种仅在 Spring MVC web 环境生效。

1.1 6 种作用域详解

作用域 核心说明 适用场景
singleton 默认作用域,每个 Spring IoC 容器内同名称 Bean 仅 1 个实例,全局共享 无状态对象(如 Service、Dao)
prototype 每次获取 Bean 时创建新实例,容器仅负责创建,不管理销毁 有状态对象(如请求参数对象)
request 每个 HTTP 请求生命周期内创建 1 个实例,请求结束后销毁 单次请求内共享数据
session 每个 HTTP Session 生命周期内创建 1 个实例,会话失效后销毁 用户会话内共享数据(如登录信息)
application 每个 ServletContext 生命周期内 1 个实例,等同于 web 应用全局单例 应用级共享数据(如全局配置)
websocket 每个 WebSocket 连接生命周期内 1 个实例,连接关闭后销毁 实时通信场景

1.2 作用域代码实现

通过@Scope注解指定 Bean 的作用域,不同作用域对应不同的注解取值:

import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.context.annotation.SessionScope;

@Component
public class DogBeanConfig {
    // 单例作用域(默认,可省略@Scope)
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Dog singleDog() {
        return new Dog();
    }

    // 原型作用域
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Dog prototypeDog() {
        return new Dog();
    }

    // 请求作用域(等同于@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS))
    @Bean
    @RequestScope
    public Dog requestDog() {
        return new Dog();
    }

    // 会话作用域
    @Bean
    @SessionScope
    public Dog sessionDog() {
        return new Dog();
    }
}

1.3 作用域关键特性验证

  • singleton:多次从容器获取 Bean,地址一致,修改一个实例会影响所有引用。
  • prototype:每次getBean()获取的实例地址不同,容器启动时不初始化,仅在获取时创建。
  • request:同一请求内获取的 Bean 地址一致,不同请求则不同。
  • session:同一浏览器会话内 Bean 地址一致,换浏览器(新会话)则重新创建。

二、Bean 的生命周期:从创建到销毁的完整流程

Bean 的生命周期是指 Bean 从容器中诞生到最终销毁的全过程,共分为 5 个核心阶段,其中初始化和销毁阶段支持用户自定义扩展。

2.1 生命周期 5 大阶段

  1. 实例化(Instantiation):为 Bean 分配内存空间,调用类的构造函数,此时 Bean 仅为 “空对象”,属性未赋值。
  2. 属性赋值(Populate):通过@Autowired、Setter 方法或构造函数注入依赖的 Bean,为 Bean 的属性赋值。
  3. 初始化(Initialization):Bean 功能完善阶段,执行顺序为:
    • 调用BeanNameAwareBeanFactoryAware等接口方法(获取容器信息);
    • 执行@PostConstruct注解标注的初始化方法;
    • 执行InitializingBean接口的afterPropertiesSet()方法;
    • 执行 XML 配置或@Bean指定的init-method方法。
  4. 使用(Usage):Bean 处于可用状态,供应用程序调用。
  5. 销毁(Destruction):容器关闭时执行,顺序为:
    • 执行@PreDestroy注解标注的销毁方法;
    • 执行DisposableBean接口的destroy()方法;
    • 执行 XML 配置或@Bean指定的destroy-method方法。

2.2 生命周期代码演示

通过实现接口与注解,自定义 Bean 的生命周期行为:

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BeanLifeComponent implements BeanNameAware {
    private UserComponent userComponent;

    // 1. 实例化:执行构造函数
    public BeanLifeComponent() {
        System.out.println("1. 执行构造函数(实例化)");
    }

    // 2. 属性赋值:通过Setter注入依赖
    @Autowired
    public void setUserComponent(UserComponent userComponent) {
        this.userComponent = userComponent;
        System.out.println("2. 执行属性赋值");
    }

    // 3. 初始化:实现BeanNameAware接口,获取Bean名称
    @Override
    public void setBeanName(String s) {
        System.out.println("3. 执行setBeanName(Aware接口):" + s);
    }

    // 3. 初始化:@PostConstruct注解标注初始化方法
    @PostConstruct
    public void postConstruct() {
        System.out.println("4. 执行@PostConstruct(初始化)");
    }

    // 4. 使用:Bean的业务方法
    public void use() {
        System.out.println("5. 执行use方法(使用Bean)");
    }

    // 5. 销毁:@PreDestroy注解标注销毁方法
    @PreDestroy
    public void preDestroy() {
        System.out.println("6. 执行@PreDestroy(销毁)");
    }
}

运行后输出顺序与生命周期阶段完全一致,清晰展现了 Bean 从创建到销毁的全过程。

2.3 生命周期源码核心逻辑

Bean 的生命周期在 Spring 源码中通过AbstractAutowireCapableBeanFactory类的方法实现,核心对应关系如下:

  • createBeanInstance():实例化 Bean,调用构造函数;
  • populateBean():属性赋值,注入依赖;
  • initializeBean():初始化 Bean,执行 Aware 接口、初始化方法;
  • 销毁逻辑则通过DisposableBeanAdapter类触发,调用销毁相关方法。

三、SpringBoot 自动配置:“开箱即用” 的底层原理

SpringBoot 自动配置的核心是:容器启动时,自动加载依赖 Jar 包中的配置类与 Bean 到 IoC 容器,无需手动声明,其本质是通过@SpringBootApplication注解封装了三大核心能力。

3.1 自动配置的核心入口:@SpringBootApplication

@SpringBootApplication是一个组合注解,包含三个关键子注解,共同实现自动配置:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration // 1. 标志当前类为配置类
@EnableAutoConfiguration  // 2. 开启自动配置(核心)
@ComponentScan            // 3. 扫描当前包及子包的Bean
public @interface SpringBootApplication {
    // 省略属性...
}

三个子注解的作用分别是:

  1. @SpringBootConfiguration:本质是@Configuration,标注当前类为配置类,支持定义@Bean
  2. @ComponentScan:默认扫描启动类所在包及子包,将标注@Controller@Service等注解的类注入容器。
  3. @EnableAutoConfiguration:自动配置的核心,通过导入配置类实现 Bean 的自动加载。

3.2 自动配置的核心逻辑:@EnableAutoConfiguration

@EnableAutoConfiguration通过@Import导入AutoConfigurationImportSelector类,该类负责加载所有自动配置类,核心流程如下:

  1. 加载配置类列表AutoConfigurationImportSelectorselectImports()方法调用getCandidateConfigurations(),读取所有依赖 Jar 包中META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中的配置类全路径。
  2. 过滤生效配置类:通过@Conditional系列注解(如@ConditionalOnClass@ConditionalOnMissingBean)动态判断配置类是否生效。例如RedisAutoConfiguration仅在类路径存在RedisOperations类且容器中无RedisTemplateBean 时才生效。
  3. 注入容器:生效的配置类被加载到 IoC 容器,其内部@Bean标注的方法会创建 Bean 并注入容器,实现 “开箱即用”。

3.3 第三方依赖的自动配置适配

当引入第三方依赖(如 MyBatis、Redis)时,无需手动配置,因为第三方依赖已按 SpringBoot 约定,在自身 Jar 包中提供了META-INF/spring.factories文件,声明了自动配置类。SpringBoot 启动时会自动扫描这些文件,加载对应的配置类与 Bean。

四、核心知识点总结

  1. Bean 作用域:6 种作用域对应不同的实例创建策略,默认singletonprototype适用于有状态对象,web 环境专用作用域(request/session等)需结合 web 场景使用。
  2. Bean 生命周期:5 大阶段(实例化→属性赋值→初始化→使用→销毁),初始化和销毁阶段支持通过注解(@PostConstruct/@PreDestroy)或接口自定义行为。
  3. SpringBoot 自动配置:核心是@SpringBootApplication注解,通过@EnableAutoConfiguration导入依赖中的配置类,结合@Conditional注解动态生效,实现 “开箱即用”。

理解这些原理,不仅能解决日常开发中的 Bean 管理问题,更能在需要自定义配置或排查自动配置问题时,快速定位核心原因,提升 Spring 生态的使用深度。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐