一文搞懂Spring Bean:从“普通类”到“被容器管理的对象”
📌 写在前面
刚开始学Java时,我们习惯这样创建对象:User user = new User()。后来学Spring,发现不用自己new了,在类上加个@Component,就能通过@Autowired拿到实例。这个被Spring管理的对象就叫Bean。
但很多初学者会困惑:Bean不就是普通对象吗?为什么要叫Bean?它和JavaBean有什么关系?为什么面试总爱问作用域和生命周期?
其实,理解Spring Bean的关键在于:它不再是你手动new出来的“孤立对象”,而是被Spring IoC容器接管了生命周期的“托管对象”。容器帮你创建、装配、管理依赖、控制销毁。
这篇笔记,我按照大多数Java学习者的认知顺序来组织:从JavaBean到Spring Bean,从注解声明到XML配置,从单例到原型,从初始化到销毁。希望能帮你彻底搞懂Spring Bean的本质。

1️⃣ 回顾JavaBean:只是一种编码规范
在Spring出现之前,JavaBean就已经存在了。它并不是一个技术,而是一套编码规范:
-
类必须是公共的(
public) -
有一个无参构造方法
-
属性用private修饰,通过
getter/setter访问 -
通常实现
Serializable接口(用于传输/存储)
public class User implements Serializable {
private String name;
private Integer age;
public User() {} // 无参构造
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// ...其他getter/setter
}
JavaBean的作用很简单:封装数据,比如从前端接收表单数据、ORM框架映射数据库记录。它只是一个普通类,需要你自己new出来。
2️⃣ Spring Bean:被IoC容器管理的对象
Spring Bean是一个被Spring IoC容器实例化、装配和管理的对象。你不再需要手动new,而是告诉Spring:“这个类交给你管理”,然后从容器中取用。
最简单的声明:注解
@Component // 标记为Spring Bean
public class UserService {
public void doSomething() {
System.out.println("Hello Bean");
}
}
在其他地方使用:
@Autowired
private UserService userService; // Spring自动注入
背后发生了什么?
-
Spring启动时,扫描带有
@Component(或其派生注解@Service、@Repository、@Controller)的类 -
通过反射创建该类的实例(默认单例)
-
将实例存入IoC容器(一个大的Map结构)
-
遇到
@Autowired时,从容器中查找匹配的Bean并注入
关键区别:普通类是你主动new,Spring Bean是被动创建并由容器管理生命周期。
3️⃣ Bean与普通类的本质区别

4️⃣ Bean的三种声明方式
虽然现代项目几乎都用注解,但理解XML和Java配置有助于深入理解Spring。
方式一:XML配置(老项目常见)
<beans>
<bean id="userService" class="com.example.UserService"/>
<bean id="userDao" class="com.example.UserDao"/>
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
UserService service = context.getBean(UserService.class);
方式二:注解(最常用)
-
@Component:通用Bean -
@Service:业务层 -
@Repository:数据访问层 -
@Controller:控制层(Web)
@Service
public class UserService { ... }
启用组件扫描(Spring Boot自动配置):
@SpringBootApplication // 内含@ComponentScan
方式三:Java配置类(Spring Boot推荐用于第三方Bean)
@Configuration
public class AppConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate() {
return new RedisTemplate<>();
}
}
选型建议:自己写的类用@Component系列;第三方库、需要复杂初始化的用@Bean。
5️⃣ Bean的作用域
作用域决定了Bean实例的创建策略。默认是单例(singleton)。

声明方式:
@Component
@Scope("prototype")
public class ShoppingCart { ... }
重要提示:当单例Bean依赖原型Bean时,原型Bean会失效(因为单例只创建一次)。解决方案:使用@Lookup注解或ObjectFactory。
6️⃣ Bean的生命周期
面试高频考点。Bean在IoC容器中的完整生命周期如下:
实例化 → 属性注入 → 初始化前 → 初始化 → 初始化后 → 使用 → 销毁前 → 销毁
各阶段关键点

示例:完整生命周期演示
@Component
public class ExampleBean implements InitializingBean, DisposableBean {
@PostConstruct
public void postConstruct() {
System.out.println("1. @PostConstruct");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("2. InitializingBean");
}
@PreDestroy
public void preDestroy() {
System.out.println("3. @PreDestroy");
}
@Override
public void destroy() throws Exception {
System.out.println("4. DisposableBean");
}
}
执行顺序:@PostConstruct → afterPropertiesSet → (使用中) → @PreDestroy → destroy
大多数业务开发不需要手动实现这些接口,但了解它们有助于排查问题(比如为什么某个Bean初始化时报错)。
7️⃣ 常见面试题与避坑指南
Q1:Spring Bean是线程安全的吗?
A:默认单例,如果Bean中没有可变的成员变量(或者使用ThreadLocal),则是线程安全的。Service、Dao通常无状态,所以安全。如果Bean有状态(如成员变量int count),则需要加锁或改为原型作用域。
Q2:@Component和@Bean的区别?
A:
-
@Component:用在自己写的类上,配合@ComponentScan自动注册 -
@Bean:用在配置类的方法上,适合创建第三方库的实例,可以自定义初始化逻辑
Q3:如何让一个Bean在初始化后执行某个方法?
A:
-
使用
@PostConstruct注解(推荐) -
实现
InitializingBean接口 -
@Bean(initMethod = "customInit")
Q4:Bean的作用域什么时候用prototype?
A:当Bean持有用户特定状态时,比如购物车、表单对象。注意prototype的Bean不会自动销毁,需要手动管理。
避坑指南
-
不要在单例Bean中直接注入原型Bean,否则原型Bean退化为单例。应使用
@Lookup或ObjectProvider。 -
避免在构造方法中执行过多逻辑,因为此时依赖可能尚未注入。
-
@PostConstruct和@PreDestroy需要引入javax.annotation-api依赖(JDK9后需单独加),但Spring Boot已默认包含。 -
理解循环依赖:Spring通过三级缓存解决了单例Bean的循环依赖,但不支持构造器循环依赖和原型Bean的循环依赖。
📌 写在最后
从普通Java对象到Spring Bean,本质上是控制权的转移:你不再主动创建对象,而是把创建和管理的权力交给Spring IoC容器。这个转变一开始可能不习惯,但随着项目变大,你会发现它能带来极大的便利:解耦、统一管理、AOP增强。
理解Spring Bean的关键,是记住三件事:
-
它是被容器管理的对象
-
默认是单例
-
生命周期有明确的回调点
希望这篇笔记能帮你从“只会用注解”到“真正理解Bean的本质”。下一篇,我计划写一篇关于Spring循环依赖的解决方案与原理,敬请期待。
如果一个单例Bean中通过@Autowired注入了一个原型Bean,那么这个原型Bean每次调用时都是新实例吗?为什么?如何解决?欢迎在评论区留下你的答案
如果这篇文章帮到了你,欢迎点赞+收藏+关注,我会持续输出相关的高质量内容。你的支持是我创作的动力!
更多推荐
所有评论(0)