【发布时间】:2014-03-25 00:15:32
【问题描述】:
我想知道什么时候应该在 Spring 中准确使用 prototype 范围?我知道如果请求 bean,singleton 返回相同的对象实例。
那我们为什么要考虑prototype?
通过示例进行解释将有助于理解对它的需求。
【问题讨论】:
标签: java spring scope singleton prototype-scope
我想知道什么时候应该在 Spring 中准确使用 prototype 范围?我知道如果请求 bean,singleton 返回相同的对象实例。
那我们为什么要考虑prototype?
通过示例进行解释将有助于理解对它的需求。
【问题讨论】:
标签: java spring scope singleton prototype-scope
明确简单的定义:
原型范围 = 每次注入/查找时都会创建一个新对象。每次都会使用新的SomeBean()。
单例范围 = 每次注入/查找时都返回相同的对象。在这里它会实例化一个SomeBean 的实例,然后每次都返回它。
原型 bean 在使用时创建。因此,当您希望拥有有状态的 bean 时,有时强烈需要拥有原型范围,或者当您不想在 bean 中缓存任何值时。原型 bean 可以与一个会话或某个调用相关联。
例子:
数据访问对象 (DAO) 通常不配置为原型,因为典型的 DAO 不保持任何会话状态;对这位作者来说,重用单例图的核心更容易。
【讨论】:
有一些有趣的用例,通过使用范围原型,您将构建更好、更可靠的应用程序设计/架构,例如实时系统。
假设您必须建立一个实时车辆跟踪系统,您将有 2.000.000 辆汽车每 5 秒共享信息, 在服务器端,您将使用两组或更多组不同的配置,一组用于汽车,另一组用于卡车。
基于这个简单的示例,如果您将应用程序设计为通过原型模式在内存中使用不同的配置组,您将获得更好的性能。
因此,在这种情况下,例如,每当服务器收到来自卡车的新消息时,服务器都会从 VehicleGrupConfiguration 实例的哈希映射中获取内存中的配置实例,然后应用此消息必须具有的配置行为,例如:超时、重试...等。
我想强调一下,有很多方法可以实现这种情况,但是这个例子表明原型模式在性能和设计模式方面非常强大。
【讨论】:
LocalContainerEntityManagerFactoryBean 类型的配置bean,一个名为userEntityManager,另一个名为productEntityManager。
如文档所述,创建具有原型范围的 Bean Foo 与调用相同:
Foo foo = new Foo(dependency1, dependency2, ...);
foo.initialize(dependency7, dependency8...);
使用原型作用域 bean 而不是 new 的唯一充分理由是,用于创建和初始化实例的依赖项应保留在需要新实例的代码之外。
举个例子:
// need to explicitly mention dependencies here
public void createdWithNew(Dependency dependency1, Dependency dependency2) {
Foo foo = new Foo(dependency1, dependency2, ...);
foo.doSomething();
}
// Dependencies managed in class Foo by Spring
public void createdWithSpring(Foo foo) {
foo.doSomething();
}
例如,如果您想编写类似于 EJB2 Java Entity bean 的持久性代码,例如
Person p = ...
p.setName("John Doe");
p.save(); // write to DB
而不是使用JPA方式
Person p = new Person();
p.setName("John Doe");
personService.save(p); // write to DB
在实体 bean 代码风格中,person 实例需要知道它应该如何被持久化,因此它需要被注入写一个人的代码不应该知道的持久化细节。
另一个例子: 如果您想在应用程序的许多地方使用非线程安全的 SimpleDateFormat Java 类,并使用配置文件中的格式模式(可能根据其他条件使用不同的格式)。与其在所有这些地方创建一个新的格式实例,还从文件(或弹簧属性)加载格式字符串,您可以使用原型范围每次都获取一个新的实例,设置通用格式的详细信息在一个地点。
【讨论】: