从组件 bean 获取原型 bean 的正确设计模式是什么?
What is the right design pattern to get a prototype-bean from a component-bean?
我只是想知道好的架构设计是什么样的。
- 假设我们有一个
CarRepository
,它管理汽车租赁应用程序中所有 Car
类型的 bean。
Car
bean 是原型类型
CarRepository
bean 是存储库类型(单例)
- 现在,
CarRepository
被要求创建一个新的 Car
bean,例如当租车公司买了新车。
当然,我可以实现ApplicatioContextAware
并使用context.getBean("car")
,但对我来说,它不太适合依赖注入的想法。将寿命较短的 bean 注入单例的最佳实践是什么?
更新:也许我应该添加一个示例以使其更清楚。
@Repository
public class CarRepository {
private List<Car> cars;
public void registerNewCar(int id, String model) {
// I don't want to access the Spring context via ApplicationContextAware here
// Car tmp = (Car) context.getBean("car");
// car.setId(id);
// car.setModel(model);
// cars.add(tmp);
}
}
@Scope("prototype")
public class Car {
private int id;
private String model;
// getter and setters
}
如果你不想用context.getBean(...)
,那么你可以用new Car(...)
造车,效果一样。
只有这两种方法!
Spring 提供了一种机制,可以处理将较短寿命的 bean 注入到较长寿命的 bean 中。它称为作用域代理。它的工作原理是单例注入了一个代理,该代理将通过搜索 bean 实例的较短范围(如会话或请求)并委托给该实例来处理方法调用。
如果您使用 xml 或注释来配置您的应用程序,或者您使用的 Spring 版本,您没有指定。您可以在 reference guide 中阅读有关使用 xml 配置作用域代理的更多信息。我将举例说明如何在 Spring 4-ish 环境中使用注释配置它。
对我来说最好的方法是使用元注释机制。它允许您创建自己的注释,稍后 Spring 将使用这些注释来配置您的应用程序。例如:
@Retention(RUNTIME)
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.TARGET_CLASS)
public @interface SessionScoped{
}
当在@Component(或@Service 或任何其他专业)class 或您的Java 配置中的@Bean 方法上指定时,这样的注解将导致该bean 被注入为一个代理。例如:
@Configuration
@EnableAspectJAutoProxy
public class MyConfig{
@SessionScoped
@Bean
public MyClass myBean(){
// return your bean
}
}
综上所述,您的示例确实让我觉得您应该使用实体 (Car) 和存储库。如果您正在设计模型层并且想将 Cars 数据存储在数据库等中,请参阅 Spring Data
我只是想知道好的架构设计是什么样的。
- 假设我们有一个
CarRepository
,它管理汽车租赁应用程序中所有Car
类型的 bean。 Car
bean 是原型类型CarRepository
bean 是存储库类型(单例)- 现在,
CarRepository
被要求创建一个新的Car
bean,例如当租车公司买了新车。
当然,我可以实现ApplicatioContextAware
并使用context.getBean("car")
,但对我来说,它不太适合依赖注入的想法。将寿命较短的 bean 注入单例的最佳实践是什么?
更新:也许我应该添加一个示例以使其更清楚。
@Repository
public class CarRepository {
private List<Car> cars;
public void registerNewCar(int id, String model) {
// I don't want to access the Spring context via ApplicationContextAware here
// Car tmp = (Car) context.getBean("car");
// car.setId(id);
// car.setModel(model);
// cars.add(tmp);
}
}
@Scope("prototype")
public class Car {
private int id;
private String model;
// getter and setters
}
如果你不想用context.getBean(...)
,那么你可以用new Car(...)
造车,效果一样。
只有这两种方法!
Spring 提供了一种机制,可以处理将较短寿命的 bean 注入到较长寿命的 bean 中。它称为作用域代理。它的工作原理是单例注入了一个代理,该代理将通过搜索 bean 实例的较短范围(如会话或请求)并委托给该实例来处理方法调用。
如果您使用 xml 或注释来配置您的应用程序,或者您使用的 Spring 版本,您没有指定。您可以在 reference guide 中阅读有关使用 xml 配置作用域代理的更多信息。我将举例说明如何在 Spring 4-ish 环境中使用注释配置它。
对我来说最好的方法是使用元注释机制。它允许您创建自己的注释,稍后 Spring 将使用这些注释来配置您的应用程序。例如:
@Retention(RUNTIME)
@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode=ScopedProxyMode.TARGET_CLASS)
public @interface SessionScoped{
}
当在@Component(或@Service 或任何其他专业)class 或您的Java 配置中的@Bean 方法上指定时,这样的注解将导致该bean 被注入为一个代理。例如:
@Configuration
@EnableAspectJAutoProxy
public class MyConfig{
@SessionScoped
@Bean
public MyClass myBean(){
// return your bean
}
}
综上所述,您的示例确实让我觉得您应该使用实体 (Car) 和存储库。如果您正在设计模型层并且想将 Cars 数据存储在数据库等中,请参阅 Spring Data