-1

假设有一个应用程序在每次需要处理一些数据时都会创建一个 Task 类的实例。任务实例中注入了一些其他服务,但所有这些服务和任务对象本身在单个任务实例中都是唯一的。当然也注入了一些全局服务,但它们是真正的应用程序范围的单例。所以我的问题是配置注入本地(或作用域)单例实例的最佳方法是什么?我主要考虑使用子上下文,但如何正确配置它仍然是我的问题。还要提到的一件事是我使用注释和基于 java 的配置。

4

4 回答 4

1

我认为自定义范围是您所要求的。但是,请注意:您所描述的痛点通常是由于过度紧密耦合的设计造成的,而不是在 IOC 容器内部的合理需要。您可能是真正有这种合法需求的少数人之一,但重新设计更有可能以更清洁的方式解决您的问题。

于 2013-12-11T20:00:57.773 回答
0
 private static final SingletonObject singleton = new SingletonObject();

Private 只能在本地访问。静态只做一个。最终阻止它改变。

如果您需要阻止其他人创建更多 SingletonObjects,我将需要更多上下文信息并且可能是不可能的 - 但在大多数情况下,不阻塞这实际上不是问题。

于 2013-12-11T15:55:20.690 回答
0

如果我没记错的话,你想让
“任务”类有两个实例变量,因为
“子任务”每个任务实例应该只有一个实例
“全局任务”每个应用程序/Spring IOC 上下文应该只有一个实例,
并且每次创建“任务” " 您要创建 unquie "SubTask" 的实例并使用相同的 GlobalTask​​ 实例。

如果这是真的,我不明白
你可以通过将“Task”和“SubTask”声明为原型并将“GlobalTask​​”作为默认的 SingleTon 来解决什么问题,如下所示

@Component("Task")

@Scope("prototype") 公共类任务 {

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("prototype") 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");
}

}

于 2013-12-11T18:40:35.663 回答
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);
        }
    }
}
于 2014-01-20T03:06:15.150 回答