Springboot Bean是什么
Bean 是一个由 Spring IoC(Inversion of Control,控制反转)容器 管理的对象。它是 Spring 应用的核心构建块,几乎所有的组件(如服务、控制器、仓库等)都会被定义为 Bean,以便 Spring 容器能够统一创建、配置、管理和销毁它们。
什么是loc
传统开发中,对象的创建和依赖管理由开发者手动控制(例如 new UserService()、userService.setDao(new UserDao()))。
而 Spring 的 IoC 容器会反转这种控制权:开发者只需声明对象的 “需求”(如需要一个 UserService),容器会自动负责对象的创建、依赖注入(DI)、生命周期管理(初始化、销毁)等,开发者直接使用容器提供的对象即可。
Bean 的本质
- Bean 本质上是一个普通的 Java 对象(POJO),但它的创建、配置和生命周期由 Spring 容器掌控,而非开发者手动管理。
- 容器通过读取配置(注解或 XML),识别哪些类需要被实例化为 Bean,然后将这些 Bean 存入一个 “容器”(可以理解为一个 Bean 仓库),后续需要时直接从容器中获取,无需重复创建。
如何创建 Bean?
Spring Boot 推荐使用 注解驱动 的方式创建 Bean,常用注解如下:
| 注解 | 作用 | 适用场景 |
|---|---|---|
@Component |
通用注解,标记一个类为 Spring Bean | 不确定具体层级的组件(如工具类) |
@Service |
专门标记 “服务层” 组件(业务逻辑) | Service 层(如 UserService) |
@Repository |
专门标记 “数据访问层” 组件(DAO) | Repository 层(如 UserDao) |
@Controller |
专门标记 “控制层” 组件(接收请求) | Controller 层(如 UserController) |
@RestController |
组合 @Controller 和 @ResponseBody |
RESTful 接口的 Controller |
@Configuration + @Bean |
手动声明 Bean(适用于第三方类) | 无法直接修改源码的类(如 DataSource) |
用 @Configuration + @Bean 创建 Bean
如果需要将第三方类(如数据库连接池 DataSource)注册为 Bean,可通过配置类手动声明:
// 标记为配置类,容器会扫描其中的 @Bean 注解
@Configuration
public class DataSourceConfig {
// 声明一个名为“dataSource”的 Bean,容器会调用该方法创建实例
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("123456");
return new HikariDataSource(config);
}
}
Bean 的生命周期
Spring Bean 的生命周期可以概括为以下关键阶段(简化版):
- 实例化:容器根据 Bean 定义创建 Java 对象(调用构造方法)。
- 依赖注入:容器自动注入 Bean 的依赖(如
@Autowired标记的属性)。 - 初始化:
- 调用
@PostConstruct注解的方法(自定义初始化逻辑)。 - 执行
InitializingBean#afterPropertiesSet()方法(若实现该接口)。
- 调用
- 就绪可用:Bean 进入容器的 “Bean 池”,等待被其他组件调用。
- 销毁:
- 容器关闭时,调用
@PreDestroy注解的方法(自定义销毁逻辑)。 - 执行
DisposableBean#destroy()方法(若实现该接口)。
- 容器关闭时,调用
示例:生命周期回调
@Component
public class MyBean {
// 构造方法(实例化阶段调用)
public MyBean() {
System.out.println("Bean 实例化:MyBean 构造方法执行");
}
// 依赖注入(实例化后调用)
@Autowired
private UserService userService;
// 初始化方法(依赖注入后调用)
@PostConstruct
public void init() {
System.out.println("Bean 初始化:@PostConstruct 执行");
}
// 销毁方法(容器关闭时调用)
@PreDestroy
public void destroy() {
System.out.println("Bean 销毁:@PreDestroy 执行");
}
}
Bean 的作用域
Bean 的 “作用域” 定义了 Bean 实例的创建方式和生命周期范围。Spring 支持多种作用域,常用的有:
| 作用域 | 说明 | 适用场景 |
|---|---|---|
singleton |
默认,容器中仅存在一个 Bean 实例 | 无状态组件(如 Service、Dao) |
prototype |
每次请求 Bean 时,都创建一个新实例 | 有状态组件(如 Command、Request 级别的对象) |
request |
每个 HTTP 请求对应一个 Bean 实例 | Web 应用中,与请求相关的组件 |
session |
每个 HTTP Session 对应一个 Bean 实例 | Web 应用中,与会话相关的组件 |
application |
整个 Web 应用共享一个 Bean 实例 | Web 应用的全局配置组件 |
示例:设置 Bean 作用域
// 将作用域设置为 prototype(每次请求创建新实例)
@Component
@Scope("prototype")
public class MyPrototypeBean {
// ...
}
使用Bean来导入配置文件
当项目中存在多个数据源时,需要配置多个事务管理器,并通过 @Transactional 的 transactionManager 属性指定使用哪个事务管理器。
示例配置:
- 配置多个数据源:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
// 主数据源(默认使用)
@Primary
@Bean
@ConfigurationProperties("spring.datasource.main")
public DataSource mainDataSource() {
return new HikariDataSource();
}
// 第二个数据源
@Bean
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondaryDataSource() {
return new HikariDataSource();
}
// 主事务管理器(默认使用)
@Primary
@Bean
public PlatformTransactionManager mainTransactionManager() {
return new DataSourceTransactionManager(mainDataSource());
}
// 第二个事务管理器
@Bean
public PlatformTransactionManager secondaryTransactionManager() {
return new DataSourceTransactionManager(secondaryDataSource());
}
}
配置文件(application.yml)
spring:
datasource:
main:
url: jdbc:mysql://localhost:3306/main_db
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
使用多个事务管理器:
@Service
public class MultiDataSourceService {
private final MainUserRepository mainUserRepository;
private final SecondaryUserRepository secondaryUserRepository;
public MultiDataSourceService(MainUserRepository mainUserRepository, SecondaryUserRepository secondaryUserRepository) {
this.mainUserRepository = mainUserRepository;
this.secondaryUserRepository = secondaryUserRepository;
}
// 使用主事务管理器(默认)
@Transactional(transactionManager = "mainTransactionManager")
public void createMainUser(String username) {
mainUserRepository.save(new MainUser(username));
}
// 使用第二个事务管理器
@Transactional(transactionManager = "secondaryTransactionManager")
public void createSecondaryUser(String username) {
secondaryUserRepository.save(new SecondaryUser(username));
}
}