Bean 到底是什么?
在 Spring 的世界里,一个 Bean 是一个由 Spring IoC 容器实例化、组装、和管理的对象。
简单来说,它不再是一个普通的、孤立的对象,而是一个被“收编”进 Spring 大家庭、有“户口”、接受统一管理的“公民”。
这个“管理”意味着什么?
- 它的创建不归你管:你不用再写
new MyService(),Spring 容器会帮你创建。 - 它的依赖不归你管:它需要什么其他对象(比如
MyRepository),Spring 容器会自动“注入”给它。 - 它的生命周期不归你管:它什么时候初始化、什么时候销毁,都由容器精确控制。
- 它可以获得“超能力”:正因为被容器管理,Spring 才有机会给它附加各种功能,比如事务管理(
@Transactional)、缓存(@Cacheable)等。
它和一个普通的 Java 对象(POJO)有什么区别和联系?
联系:
一个 Bean 的本质,就是一个 Java 对象(POJO)。
Spring 并没有发明一种新的对象类型。前面文章中咱们写的 UserService 类,它本身就是一个 POJO (Plain Old Java Object)。Spring 做的不是改变这个对象,而是改变了这个对象的管理方式。
区别:
核心区别在于控制权和生命周期。一个对象是普通的 POJO 还是 Spring Bean,取决于它是由谁创建和管理的。
| 特性 | 普通 Java 对象 (POJO) | Spring Bean |
|---|---|---|
| 创建方式 | 由程序员手动 new | 由 Spring IoC 容器根据配置(注解/XML)创建 |
| 控制权 | 程序员完全控制 | 控制权反转给了 IoC 容器 |
| 生命周期 | 由 JVM 的垃圾回收机制管理,作用域取决于代码块 | 由 IoC 容器管理(实例化 -> 依赖注入 -> 初始化 -> 使用 -> 销毁) |
| 依赖关系 | 需要手动创建并传入依赖 (new Service(new Repo())) | 由容器通过依赖注入自动装配 |
| 作用域 | 每次 new 都是一个新实例 | 可由容器配置多种作用域(如 singleton 单例、prototype 原型等) |
| 获取的超能力 | 无,只是一个普通对象 | 可通过 AOP 轻松获得事务、安全、缓存等企业级服务 |
例子:从 POJO “晋升”为 Bean
让我们看看一个对象是如何从一个“普通人”(POJO)变成一个“有编制的公民”(Bean)的。
第1步:一个纯粹的 POJO
这是一个普通的 Java 类,没有任何 Spring 的痕迹。
// EmailService.java - 这是一个纯粹的POJO
public class EmailService {
public void sendEmail(String to, String body) {
System.out.println("正在发送邮件给 " + to + ": " + body);
}
}
如何使用它? 必须自己 new!
public class MyApp {
public static void main(String[] args) {
// 我自己创建,自己管理
EmailService emailService = new EmailService();
emailService.sendEmail("test@example.com", "Hello POJO!");
}
}
此时的 emailService 就是一个普通的 POJO。
第2步:“晋升”为 Spring Bean
我们对 EmailService 类本身几乎不做改动,只是给它戴上一顶“帽子”——一个 Spring 注解。
import org.springframework.stereotype.Service;
// 戴上@Service的帽子后,它就有资格成为一个Bean了
@Service
public class EmailService {
public void sendEmail(String to, String body) {
System.out.println("正在发送邮件给 " + to + ": " + body);
}
}
如何使用它? 我们不再 new 它,而是向 Spring 容器“索取”。
@Configuration
@ComponentScan
public class MyApp {
public static void main(String[] args) {
// 1. 启动Spring容器,容器会扫描并创建所有戴了帽子的Bean
ApplicationContext context = new AnnotationConfigApplicationContext(MyApp.class);
// 2. 我不再自己创建,而是向容器要一个已经准备好的实例
EmailService emailService = context.getBean(EmailService.class);
emailService.sendEmail("test@example.com", "Hello Bean!");
}
}
EmailService.java这个类文件几乎没变。- 但是,通过
@Service注解和 Spring 容器的介入,由context.getBean()获取的那个emailService实例,其身份已经完全不同了。它现在是一个 Bean。
总结
- 联系:Bean 的“原材料”就是一个普通的 Java 对象(POJO)。
- 区别:Bean 是被 Spring IoC 容器“收养并赋予超能力”的 POJO。
- 核心:这个区别不在于对象本身的代码,而在于它是否被纳入了 IoC 容器的管理体系。
你可以这样记忆:
所有的 Spring Bean 都是 Java 对象,但并非所有的 Java 对象都是 Spring Bean。 只有那些被 IoC 容器管理起来的,才能被称为 Bean。
2366

被折叠的 条评论
为什么被折叠?



