多例(prototype)Bean

一、多例(prototype)Bean 的创建时机

多例 Bean 不存在"预初始化"行为,其创建时机严格遵循"按需创建"原则,即每次通过 Spring 容器获取 Bean 时才会创建新的实例,具体触发场景包括:

  • 主动获取:通过 Spring 上下文(ApplicationContext)的 context.getBean(BeanClass.class)context.getBean("beanName") 方法主动获取时,创建新实例;

  • 依赖注入:当其他 Bean(单例或多例)依赖该多例 Bean 时,注入过程中会创建新实例(注:单例 Bean 依赖多例 Bean 时存在特殊问题,详见下文)。

测试场景价值:该特性确保每个测试用例获取的多例 Bean 都是全新的、无历史状态的实例,避免前一个测试用例的操作影响后一个测试用例的结果(如测试用例1修改了 Bean 的成员变量,测试用例2获取新实例可避免受该修改影响)。

二、多例(prototype)Bean 的生命周期特点

与单例 Bean 不同,多例 Bean 的生命周期管理具有"不完整"特性,Spring 仅负责前两个阶段,后续阶段由调用者和 GC 主导:

  1. Spring 负责阶段:Bean 的创建(实例化)和初始化(如执行 @PostConstruct 注解方法、实现 InitializingBean 接口的 afterPropertiesSet() 方法);

  2. Spring 不负责阶段:Bean 的销毁。多例 Bean 实例创建后,其生命周期控制权完全交给调用者,Spring 不会跟踪实例的引用状态,也不会主动触发销毁方法(如 @PreDestroy 注解方法、实现 DisposableBean 接口的 destroy() 方法);

  3. 最终回收:当多例 Bean 实例不再被任何对象引用时,由 JVM 的垃圾回收器(GC)自动回收,释放内存资源。

测试场景注意:若多例 Bean 持有资源(如数据库连接、文件流),测试完成后需手动调用自定义的资源释放方法,避免资源泄露影响测试环境稳定性。

三、测试场景核心注意:依赖注入的特殊规则

测试场景中,多例 Bean 与单例 Bean 的依赖注入存在明确的规则差异,若误用会导致测试结果异常,需重点关注

1. 多例 Bean 中注入单例 Bean:允许且正常生效

多例 Bean 中注入单例 Bean 是完全合法的,且符合预期:单例 Bean 由 Spring 容器全局管理,仅存在一个实例,该实例会被所有多例 Bean 共享。

测试场景示例:多个测试用例对应的多例测试 Bean 注入同一个单例的数据源 Bean,确保所有测试用例使用相同的数据源连接,保障测试环境的一致性。

2. 单例 Bean 中注入多例 Bean:存在失效问题,需特殊处理

这是测试场景中最易踩坑的点:单例 Bean 仅在容器启动时初始化一次,初始化过程中会注入依赖的多例 Bean------此时注入的是第一次创建的多例 Bean 实例,后续单例 Bean 复用过程中,不会再次创建新的多例实例,导致多例 Bean 失去"每次获取均为新实例"的特性,即"多例失效"。

测试场景影响:若测试用例依赖的单例 Bean 内部持有多例 Bean,多个测试用例会共享同一个多例 Bean 实例,出现测试用例间的状态干扰,导致测试结果不准确。

解决方案:在单例 Bean 中通过 Spring 上下文(ApplicationContext)动态获取多例 Bean,而非直接依赖注入。具体实现方式:

  • 让单例 Bean 实现 ApplicationContextAware 接口,通过重写 setApplicationContext(ApplicationContext context) 方法获取上下文;

  • 每次需要使用多例 Bean 时,通过context.getBean(PrototypeBean.class) 动态获取,确保每次获取的都是新实例。

测试场景使用建议

  1. 优先用于状态化测试组件:如测试用例的参数载体、测试数据上下文等,确保每个测试用例的状态独立;

  2. 避免多例 Bean 持有持久化资源:若必须持有,需在测试用例的 @After方法中手动释放资源;

  3. 单例依赖多例时强制动态获取:在测试代码或被测试的单例 Bean 中,通过 ApplicationContext 动态获取多例 Bean,规避多例失效问题;

  4. 结合测试框架注解:在 Spring Boot 测试中,可通过 @SpringBootTest 加载上下文后,在每个测试用例中通过 @Autowired 结合动态获取的方式使用多例 Bean,保障测试灵活性。

相关推荐
apolloyhl3 天前
Prototype 原型模式
原型模式
java porter4 天前
一文深度解读原型模式
java·原型模式
茶本无香5 天前
设计模式之二—原型模式:灵活的对象克隆机制
java·设计模式·原型模式
qq_406176147 天前
关于JavaScript中的filter方法
开发语言·前端·javascript·ajax·原型模式
遇见~未来7 天前
JavaScript构造函数与Class终极指南
开发语言·javascript·原型模式
sxlishaobin10 天前
设计模式之原型模式
设计模式·原型模式
Geoking.12 天前
【设计模式】原型模式(Prototype Pattern)详解
设计模式·原型模式
syt_101321 天前
js基础之-如何理解js中一切皆对象的说法
开发语言·javascript·原型模式
JavaBoy_XJ25 天前
创建型-原型模式
原型模式