我喜欢依赖注入框架以及它们如何允许我从一开始就请求一个对象。所有接线都是在第一次请求时进行的,即#34; master"宾语。 但是,有些对象应该在运行时创建,例如基于用户输入。有时,这些新创建的对象应该在框架创建的其他对象之间共享。
我目前的做法是"未初始化"框架注入的对象。在运行期间,我尽快使用setter方法设置对象。
我不喜欢这种方法的方法是,setter方法实际上只被调用一次,然后再也不会被触及。这使我无法将字段声明为final。我现在不知道如何在不丢失DI框架的所有好处之前创建对象,而不会丢失所有必要的信息。
我是DI的新手。这有什么好的模式吗?
示例:
// The service is used through out the application
interface Service {
makeRequest()
}
用户输入凭据后我想要做什么:
new ConcreteService(username, password)
// but now I need to inject the concrete servive manually everywhere I need it!
我目前正在做的事情:
interface Service {
makeRequest()
setCredentials(username, password)
}
// service can be injected by framework, but I don't like setter methods
// that much (and they can pollute the interface)
答案 0 :(得分:1)
我在依赖注入方面的大部分经验都是使用C#,但我相信无论使用何种语言,这个概念都是一样的。
我从原始海报中了解到的是,他试图“坚持”#34;依赖注入容器内的信息,以便稍后检索信息。
这种方法的问题在于,在多线程场景中,您使用的用于保留信息的依赖关系可能会被另一个线程覆盖其值。这可能发生,因为依赖注入容器通常包含对象的单个实例,只要您需要它就会返回给您。因此,您需要确保您的设计是线程安全的。
根据我的经验,使用依赖注入容器来维护状态是不好的。
您在依赖注入容器中注册的是提供"服务的对象"并且不维持任何州。
用于保存信息的对象通常是业务对象。这些业务对象应该用" new"来实例化。 (没有依赖注入容器),以通常的方式填充它们(使用setter或初始化方法或构造函数),并将其作为服务公开的操作的签名的一部分传递。
注意:您可以将您的依赖关系注册为" transient"这将告诉依赖注入容器每次请求依赖时返回一个新实例。这样可以避免使用" new"关键字显式,并在使用模拟框架编写单元测试时给予更多控制。
希望这有帮助!
答案 1 :(得分:0)
你可以做的一种方法是使用工厂。
例如,假设你有这门课程......
public class UserBean {
private int userId;
private UserService userService;
// other resources / dependency fields etc
public UserBean(int userId, UserService userService, ...other dependencies...) {
this.userService = userService;
this.userId = userId;
this.... = ...
}
// ...getter for userId maybe etc...
// Some method that uses the user's data AND the component/service you want to inject from Spring...
public void incrementHitCount() {
userService.incrementHitCount(userId);
}
}
...其中“userService”是您希望由IoC容器管理的内容。如果你有一个组件需要创建其中一个,例如....
@Component
public class UserHitCountIncrementerThing {
public ResponseBean doThatThing(HttpServletRequest request) {
int userId = request.<get the user Id from it...>
UserBean userbean = new UserBean(userId, /* need dependencies here! */);
...do stuff...
}
}
你可以在这个bean的所有服务中@Autowire,或者你可以创建一个工厂,只有@Autowire,例如......
@Component
public class UserBeanFactory {
@Autowired
private UserService userService
//...other @Autowired dependencies...
public UserBean createUser(int userId) {
return new UserBean(userService, ...etc..., userId);
}
}
现在只需在需要的地方使用它,例如......
@Component
public class UserHitCountIncrementerThing {
@Autowired
private UserBeanFactory userFactory;
public ResponseBean doThatThing(HttpServletRequest request) {
int userId = request.<get the user Id from it...>
UserBean userbean = userFactory.createUser(userId);
...do stuff...
}
}
这是你得到的吗?
希望这有帮助。