Допустим, есть приложение, которое создает экземпляр класса Task каждый раз, когда ему нужно обработать какие-то данные. В экземпляр задачи внедрены некоторые другие службы, но все эти службы и сам объект задачи уникальны в пределах одного экземпляра задачи. Конечно, некоторые глобальные сервисы также внедряются, но они являются настоящими синглтонами для всего приложения. Итак, мой вопрос: как лучше всего настроить внедрение этих локальных (или ограниченных) одноэлементных экземпляров? В первую очередь я думаю об использовании дочернего контекста, но как его правильно настроить, все еще остается для меня вопросом. Еще одна вещь, которую следует упомянуть, это то, что я использую аннотации и конфигурацию на основе Java.
Каков наилучший способ реализовать синглтон с областью действия компонента?
Ответы (4)
Я думаю, что настраиваемые области действия — это то, о чем вы просите. Тем не менее, некоторые слова предостережения: как правило, проблема, которую вы описываете, возникает из-за чрезмерно тесно связанной конструкции, а не из-за законной необходимости вставать по локоть во внутренности контейнера IOC. Вы можете быть одним из немногих людей, у которых действительно есть такая законная потребность, но гораздо более вероятно, что редизайн решит вашу проблему гораздо чище.
private static final SingletonObject singleton = new SingletonObject();
Частный, чтобы сделать доступным только локально. Статический сделать только один. Final, чтобы остановить его изменение.
Если бы вам нужно было запретить другим людям создавать больше объектов SingletonObject, мне потребовалась бы дополнительная информация о контексте, и это может быть невозможно, но в большинстве случаев отсутствие блокировки на самом деле не является проблемой.
Если я не ошибаюсь, вы хотели иметь
две переменные экземпляра класса «Задача», поскольку
«Подзадача» должна быть только одним экземпляром для каждого экземпляра задачи
«Глобальная задача» должна быть только одним экземпляром для каждого приложения / Spring. Контекст IOC
И каждый раз, когда вы создаете экземпляр «Задачи», вы хотите создать независимую «Подзадачу» и использовать один и тот же экземпляр 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("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");
}
}
Решение, которое я наконец придумал, требует создания дочернего контекста. Ключевым моментом является указание другой дочерней конфигурации, чтобы родительский контекст не знал о зависимостях дочерних компонентов. Самое простое решение — создать отдельный 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);
}
}
}
Task
. Будет ли этот код иметь доступ кApplicationContext
? - person Sotirios Delimanolis   schedule 11.12.2013The task instance have some other services injected into it but all this services and the task object itself are unique within a single task instance
- person Taylor   schedule 11.12.2013Task
и введите в него все, что хотите. Что мы упускаем? - person Sotirios Delimanolis   schedule 11.12.2013"creates an instance of the Task class every time when it needs to process some data"
Вы спрашиваете, как заполнить bean-компонент с областью действия прототипа как singleton, так и bean-компонентами с областью прототипа? Какие данные он обрабатывает? Или все это содержится в бобах-прототипах? - person Floegipoky   schedule 11.12.2013