spring-Bean

Bean是什么?

Bean 就是 Spring IOC 容器管理的对象,交给 Spring 创建、装配、生命周期管理的 Java 对象就叫 Bean;自己new出来的对象不属于 Spring Bean。

如何定义 Bean?(三种配置方式)

Spring 提供三种方式来声明 Bean,现在企业开发中注解驱动是主流:

|--------------|------------------------|------------------------------------------------|
| 方式 | 适用场景 | 示例 |
| XML 配置(老旧) | 遗留系统维护,或需要引入第三方无法改源码的类 | <bean id="userDao" class="com.dao.UserDao"/> |
| 注解定义(最常用) | 自己编写的类,直接在类上加注解 | @Component、@Service、@Repository、@Controller |
| Java 配置类(推荐) | 第三方类或需要复杂构造逻辑的 Bean | @Configuration + @Bean 写在方法上 |

@Component 和 @Bean 区别

  1. @Component:打在类上,适合自己写的业务类;由组件扫描自动发现。

  2. @Bean:打在配置类的方法上;适合第三方组件,类源码不能修改,无法加 @Component。

Bean 的作用域 scope

Spring 默认是 单例(Singleton)。

|---------------|------------------------------------|---------------------------------|
| 作用域 | 含义 | 适用场景 |
| singleton(默认) | 整个 IoC 容器中只有一个实例,所有地方共用。 | 无状态的 Service、Dao(绝大多数业务场景)。 |
| prototype | 每次从容器中 getBean() 或注入时,都新建一个实例。 | 有状态的对象(如每次请求参数不同的实体)。 |
| request | 仅对当前 HTTP 请求有效,每个请求新建一个。 | Web 层,如当前登录用户信息对象。 |
| session | 仅对当前 HTTP Session 有效。 | 用户会话级别的购物车对象。 |

Bean 完整生命周期

  1. 解析配置:扫描类,生成 BeanDefinition

  2. 实例化:反射调用构造方法,new 出空对象(此时属性还没赋值)

  3. 依赖注入 DI:给属性赋值,装配 @Autowired 依赖

  4. Aware 接口回调:BeanNameAware、ApplicationContextAware,把容器 /beanName 注入给 bean

  5. 初始化阶段

  6. ① @PostConstruct 注解方法 ② InitializingBean#afterPropertiesSet() ③ @Bean(initMethod = "xxx") 指定初始化方法

  7. Bean 就绪,可以给业务使用

  8. 容器关闭销毁 ① @PreDestroy ② DisposableBean#destroy() ③ @Bean(destroyMethod="xxx")

BeanDefinition

↓

实例化

↓

属性注入

↓

Aware 回调

↓

BeanPostProcessor

↓

初始化

↓

BeanPostProcessor

↓

Bean 可以使用

↓

容器关闭

↓

销毁

解决一个经典难题:循环依赖(三级缓存)

如果是单例 Bean,Spring 能解决 Setter 注入造成的循环依赖(如 A 依赖 B,B 依赖 A)。它利用的是三级缓存(singletonFactories),在对象实例化后、属性填充前,先把"半成品对象"提前曝光出来,从而打破闭环。

一级缓存 `singletonObjects`:完全初始化完毕的 Bean

二级缓存 `earlySingletonObjects`:实例化完成,但还没填充属性的对象,避免重复执行代理

三级缓存 `singletonFactories`:lambda 工厂,提前暴露对象引用,有可能生成代理对象

注意:构造器注入的循环依赖无法解决,Spring 会直接报错。因此,官方推荐使用 Setter 注入或字段注入来规避构造器循环依赖。

相关推荐
苍何6 小时前
开源微信流 Windows,微信聊天记录,可以直接给 Codex 和 Obsidan 了
后端
代码什么用7 小时前
Spring基础使用
java·后端·spring
代码什么用7 小时前
Spring对IoC的实现
数据库·spring
Su米苏8 小时前
Spring AI 中MCP 与普通 @Tool的区别
java·人工智能·spring
明月_清风8 小时前
Deno 终局来了:从挑战 Node 到被 Cloudflare 收编
前端·后端·node.js
码云数智-园园8 小时前
unique_ptr 还是 shared_ptr?C++ 智能指针选型与内存泄漏实战分析
java·开发语言
老板一杯拿铁8 小时前
Java 异常体系详解:从字节码原理到最佳实践
java
蜗牛互联网8 小时前
Java 17 HttpClient调用文件转写API的超时与失败回退
java·人工智能·后端
禾小西9 小时前
07丨Redis 哨兵机制:主库故障后,如何恢复服务?
java·开发语言·redis
我不是阵雨9 小时前
JDK 21虚拟线程Pinning陷阱:一文拔钉解困
java·开发语言