spring的prototype作用域本质是每次获取都新建实例,但仅当主动调用getbean()等动态获取方式时生效;若通过@autowired注入单例bean,则只在初始化时创建一次并复用。

Spring 的 prototype 作用域,本质就是“每次获取都 new 一个”,但前提是——你得真正去“获取”,而不是在注入时就固定住。
关键点:不是声明了 @Scope("prototype") 就自动每次都新
很多人误以为只要加了 @Scope("prototype"),被注入到其他 Bean 里就会自动变“新”。其实不然。Spring 在依赖注入阶段(比如构造器或 @Autowired)只做一次解析和赋值。如果一个 singleton Bean 里通过字段注入了一个 prototype Bean,那这个字段在 singleton 初始化时就被设好了,之后永远用的是同一个实例 —— 它“不翼而飞”的原因就在这。
换句话说:注入是静态绑定,获取才是动态创建。
真正每次拿到新实例的三种可靠方式
要确保每次用的都是全新对象,必须绕过“一次性注入”,改为主动、按需获取:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
用 ApplicationContext.getBean() 显式获取:在需要时调用
applicationContext.getBean(MyPrototypeBean.class),容器内部会走createBean()流程,返回新实例 -
用 ObjectFactory 或 Provider 包装:例如字段声明为
@Autowired private ObjectFactory<myprototypebean> factory;</myprototypebean>,每次调用factory.getObject()都触发新创建 -
用 @Lookup 方法(适用于类方法注入):在 singleton 类中定义一个抽象方法并标注
@Lookup,Spring 会在运行时代理该方法,每次调用都返回新 prototype 实例
XML 和注解配置写法(只是基础,不保证“每次都新”)
配置本身很简单,但仅表示“容器支持按需创建”,不改变调用逻辑:
- XML:
<bean id="service" class="com.example.MyService" scope="prototype"></bean> - 注解:
@Component @Scope("prototype") public class MyService { ... }或@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
注意:即使这样配置,若它被 @Autowired 进 singleton Bean,仍只创建一次。
为什么 Spring 不管 prototype 的销毁?
因为容器只负责“生”,不管“死”。prototype 实例一旦交给客户端(比如你的 service 方法),后续生命周期(如 close、destroy)就得你自己处理。Spring 不会调用 @PreDestroy 或销毁回调,也不会放进缓存池。如果你持有数据库连接、线程、文件句柄等资源,必须手动释放,否则容易泄漏。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










