Skip to content

Bean 是 Spring 最核心的概念,但很多人(包括当初的我)搞不清它到底是"方法"还是"类"。这篇把 Bean 的本质讲清楚:它既不是方法也不是类,而是"容器管理的对象实例";再讲清 @Component@Bean 两种定义方式的区别。

一、Bean 是什么:容器管理的对象

先分清三个概念:

概念是什么
类(class)模板/蓝图,比如 GreetingService
方法工厂方法,负责"怎么创建对象"
Bean由 Spring 容器创建并管理的对象实例

一句话:Bean = 交给 Spring 容器管理的对象。你 new 出来的对象不是 Bean(Spring 不管它),但交给 Spring 创建并放进容器的对象就是 Bean。

java
GreetingService s1 = new GreetingService();   // 普通对象,不是 Bean(Spring 不管)

@Service
class GreetingService { ... }                  // 交给 Spring,创建出来的实例是 Bean

二、三种定义 Bean 的方式

方式一:@Component / @Service 等,注解在类上

java
@Service                    // 注解在类上:这个类交给 Spring,扫描时实例化
public class UserService {
    public void save() { ... }
}

Spring 启动时扫描到 @Service,自动 new UserService() 放进容器。这是最常用的方式——你自己的类都这么干。

方式二:@Bean,注解在方法上

java
@Configuration
public class AppConfig {

    @Bean                                 // 注解在方法上:返回值交给 Spring
    public RedisTemplate redisTemplate() {   // 方法名 = Bean 名字
        return new RedisTemplate();          // 返回的对象 = Bean
    }
}

@Bean 注解在方法上,但方法本身不是 Bean——方法的返回值才是 Bean。方法名是 Bean 的名字,方法体是"怎么创建"。

方式三:XML <bean> 配置(老方式,现在很少用):

xml
<bean id="userService" class="com.example.UserService" />

三、@Component vs @Bean 怎么选

这是最容易混的点,核心区别:

维度@Component(类上)@Bean(方法上)
注解位置方法
Bean 来源这个类的实例方法的返回值
谁能用你自己的类(能改源码)第三方类(改不了源码)
场景业务类、Service、Controller第三方库的对象(RedisTemplate 等)

关键:你的类能加 @Component;但第三方库的类RedisTemplateRestTemplateDataSource)你改不了源码、加不了 @Component,就用 @Bean 方法手动 new 出来交给 Spring。

这就是为什么《Spring Boot 自动配置原理》里全是 @Bean 方法——自动配置要创建的全是第三方库的对象,只能用 @Bean 方法。

四、Bean 的作用域

Bean 默认是单例(singleton),也可以配置成其他作用域:

作用域含义
singleton(默认)整个容器只有一个实例
prototype每次获取都新建一个实例
java
@Scope("prototype")      // 每次获取都 new 一个
@Component
public class User { ... }

默认单例就是之前《单例模式》里讲的"Spring 容器缓存"——容器把 Bean 存进缓存池,大家拿到的都是同一个。

五、Bean 的生命周期(简带)

Bean 从创建到销毁,会经过几个阶段:

实例化(new) → 依赖注入 → 初始化(@PostConstruct) → 使用 → 销毁(@PreDestroy)

了解即可,日常用到最多的是 @PostConstruct(初始化后干点事,比如加载缓存)。

小结

  • Bean = Spring 容器创建并管理的对象实例,不是方法也不是类
  • 三种定义方式:@Component(类上)、@Bean(方法上,返回值是 Bean)、XML
  • 自己的类用 @Component,第三方类用 @Bean 方法
  • 默认单例,@Scope("prototype") 改成每次新建

理解了 Bean,再回头看《Spring Boot 自动配置原理》就通了——自动配置本质就是"用 @Bean 方法自动帮你建好那些 Bean"。