【问题标题】:Spring IoC - constructing context dependent beans?Spring IoC - 构建上下文相关的bean?
【发布时间】:2012-05-03 19:53:24
【问题描述】:
考虑以下代码:
@Service
class UserSpecificService {
@Autowired ServiceA serviceA;
@Autowired ServiceB serviceB;
@Autowired User user;
public void doUserSpecificThings() {
// consume serviceA, serviceB and user here
}
}
@Service class ServiceA {}
@Service class ServiceB {}
@Service
class Facade {
public void doThingsForUser(Long userId) {
User user = userService.getById(userId);
UserSpecificService userSpecificService = ...; // !!!
userSpecificService.doUserSpecificThings();
}
}
问题是关于标有// !!! 的行。有什么方法可以构造UserSpecificService 而不实现我自己的工厂,它知道ServiceA 和ServiceB,并且只需要User 的实例来实例化UserSpecificService?
如果这很重要 - 我将在 Spring MVC 中使用 Facade,尽管我不希望它依赖于此。
谢谢!
【问题讨论】:
标签:
java
spring
dependency-injection
ioc-container
【解决方案1】:
这里有一个建议:
- 让所有符合
userSpecificService 条件的服务(我猜是ServiceA 和serviceB)都有一个通用接口
- 让该接口有两个方法 -
doUserSpecificThing() 和 isEligibleFor(user)
- 使用
@Autowired List<YourInterface> list
- 在您的
doThingsForUser() 方法中迭代给定接口的所有实例的列表,并为每个实例检查它是否适合给定用户。如果是 - 调用该方法。
【解决方案2】:
如果您询问是否可以动态创建 UserSpecificService 而无需手动设置服务,请尝试以下操作:
@Configurable
class UserSpecificService {
@Autowired private ServiceA serviceA;
@Autowired private ServiceB serviceB;
private User user;
public UserSpecificService(User user){
this.user = user;
}
public void doUserSpecificThings() {
// consume serviceA, serviceB and user here
}
}
@Service class ServiceA {}
@Service class ServiceB {}
@Service
class Facade {
public void doThingsForUser(Long userId) {
User user = userService.getById(userId);
UserSpecificService userSpecificService = new UserSpecificService(user);
userSpecificService.doUserSpecificThings();
}
}
请注意,您需要配置 spring 上下文以扫描 @Configurable。为此,您只需将<context:spring-configured/> 添加到您的应用程序上下文文件中。另一种方法是:
@Service
class UserSpecificService {
@Autowired private ServiceA serviceA;
@Autowired private ServiceB serviceB;
public void doUserSpecificThings(User user) {
// consume serviceA, serviceB and user here
}
}
@Service class ServiceA {}
@Service class ServiceB {}
@Service
class Facade {
public void doThingsForUser(Long userId) {
User user = userService.getById(userId);
userSpecificService.doUserSpecificThings(user);
}
}
根据您的具体应用,这种方法可能会更好。