假设有一个应用程序在每次需要处理某些数据时都会创建Task类的实例。任务实例注入了一些其他服务,但所有这些服务和任务对象本身在单个任务实例中是唯一的。一些全球服务当然也在注入,但它们是真正的应用程序范围的单例。所以我的问题是配置注入本地(或作用域)单例实例的最佳方法是什么?我主要考虑使用子上下文,但如何正确配置它仍然是一个问题。还有一点要提到的是我使用注释和基于java的配置。
答案 0 :(得分:1)
我认为custom scopes是你所要求的。但是,有些注意事项:通常你所描述的痛点来自于过度紧密耦合的设计,而不是合法的需要在IOC容器内部到达你的肘部。你可能是少数几个真正有合法需求的人之一,但重新设计更有可能以更清洁的方式解决你的问题。
答案 1 :(得分:0)
private static final SingletonObject singleton = new SingletonObject();
私有,只能在本地访问。 静态只做一个。 最后阻止它改变。
如果你需要阻止其他人创建更多的SingletonObjects,我需要更多的上下文信息,而且可能无法实现 - 但在大多数情况下,不阻塞实际上并不是问题。
答案 2 :(得分:0)
如果我没错,你想拥有
“任务”类将两个实例变量视为
“SubTask”应该只是每个Task实例的一个实例
“GlobalTask”应该只是每个Application / Spring IOC上下文的一个实例
每次创建“任务”实例时,您都要创建unquie“SubTask”并使用相同的GlobalTask实例。
如果这是真的,我不明白是什么问题
你可以通过声明“Task”和“SubTask”作为原型来实现,“GlobalTask”默认为SingleTon,如下所示
@Component("Task")
@Scope( “原型”) 公共课程任务{
public Task(){
System.out.println("Task Created");
}
@Autowired
SubTask subTask;
@Autowired
GlobalTask globalTask;
public GlobalTask getGlobalTask() {
return globalTask;
}
public void setGlobalTask(GlobalTask globalTask) {
this.globalTask = globalTask;
}
public SubTask getSubTask() {
return subTask;
}
public void setSubTask(SubTask subTask) {
this.subTask = subTask;
}
}
@Component("SubTask")
@Scope( “原型”) public class SubTask { public SubTask(){ System.out.println(“SubTask Created”); } public void performTask(){ System.out.println(“执行任务”); } }
@Component("GlobalTask")
公共类GlobalTask {
public GlobalTask(){
System.out.println("Global task created");
}
public void performTask(){
System.out.println("Perform Global Task");
}
}
答案 3 :(得分:0)
我最终提出的解决方案需要创建子上下文。关键是指定不同的子配置,以便父上下文不知道子组件依赖性。最简单的解决方案是创建一个单独的java配置,启用组件扫描并将其放入专用包中。
@Configuration
@ComponentScan
public class TaskConfig {}
public interface TaskFactory {
Task createTask();
}
@Component
public class TaskFactoryImpl implements TaskFactory {
private ApplicationContext parentContext;
@Autowired
public void setParentContext(ApplicationContext parentContext) {
this.parentContext = parentContext;
}
@Override
public Task createTask() {
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
context.register(TaskConfig.class);
context.setParent(parentContext);
context.refresh();
return context.getBean(Task.class);
}
}
}