2013-12-11 2 views
-1

Предположим, что есть приложение, которое создает экземпляр класса Task каждый раз, когда ему нужно обработать некоторые данные. У экземпляра задачи есть некоторые другие сервисы, внедренные в него, но все эти службы и сам объект задачи уникальны в одном экземпляре задачи. Конечно, некоторые глобальные услуги тоже вводятся, но они являются истинными широкими синглонами приложений. Итак, мой вопрос заключается в том, как лучше всего настроить инъекцию этих локальных (или облачных) экземпляров singleton? Я в первую очередь думаю об использовании детского контекста, но как правильно настроить его, это все еще вопрос для меня. Еще одно замечание - использование аннотаций и java-конфигурации.Каков наилучший способ реализовать компонентный одноэлемент?

+1

Просьба указать код, который требует экземпляра 'Task'. Будет ли этот код иметь доступ к «ApplicationContext»? –

+0

Итак, вам нужны некоторые сервисы для прототипа и некоторые синглтон? Можете ли вы пояснить, что это означает: «У экземпляра задачи есть некоторые другие сервисы, внедренные в него, но все эти службы и сам объект задачи уникальны в одном экземпляре задачи» – Taylor

+0

[This] (http://stackoverflow.com/questions/20009922/pass-state-to-cdi-container-managed-beans) может помочь вам. Похоже, что подход к фабрике, о котором я рассказываю, - это, вероятно, то, что вы хотите. – Floegipoky

ответ

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); 
     } 
    } 
} 
0
private static final SingletonObject singleton = new SingletonObject(); 

Частный, чтобы сделать доступным только локально. Статический, чтобы сделать только один. Финал, чтобы остановить его.

Если вам нужно, чтобы другие люди не создавали больше SingletonObjects, мне понадобилось бы больше информации о контенте и, возможно, не удастся - но в большинстве случаев не блокировать это на самом деле не проблема.

+0

Я думаю, что цель состоит в том, чтобы получить экземпляр из контейнера Spring. –

+0

В этом случае это не локальный экземпляр, а локальная ссылка на глобальный экземпляр. Попытка использовать Spring для этого кажется огромным количеством работы для чего-то, что может быть одной линией. Единственное возможное усиление - это инъекция зависимостей, вам потребуется немного больше работы, чтобы поддержать это, но его все еще только пара строк. –

+0

@TimB. На самом деле это не пара строк. У вас может быть довольно сложный график зависимости, который может отличаться в зависимости от выбранного профиля. –

0

Если я не ошибаюсь, вы хотите иметь
«Задача» класс двух переменных экземпляра, как
«подзадачи» должен быть только один экземпляр каждого экземпляра Task
«GlobalTask» Должен быть только один экземпляр для каждого приложения/Spring IOC Context
И каждый раз, когда вы создаете экземпляр «Task», вы хотите создать unquie «SubTask» и использовать тот же экземпляр GlobalTask.

, если это правда, я не понимаю, в чем проблема
вы можете достичь, объявляя «Task» и «подзадачи» в качестве прототипа и «GlobalTask», как по умолчанию, как Синглтон, как показано ниже

@Component("Task") 

@ Scope ("прототип") общественного класса Task {

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

}

+0

Проблема с этим решением заключается в том, что когда SubTask вводится дважды в Task или где-то в иерархию объектов Task, мы будем и с двумя экземплярами SubTask, которые нежелательны. Хорошим примером является симулятор автомобилей. В игре у вас может быть много автомобилей. У каждого автомобиля есть экземпляр Engine. Двигатель уникален в иерархии объектов Car. Вы можете ввести Engine в CarComputer или в CarBody, но это будет тот же экземпляр Engine. –

+0

О, хорошо. Теперь я понимаю ваш вопрос. Вы можете попытаться реализовать CustomScope, выполнив Scope и Registry Your Scope Implementation вместо использования Seperate IOC для каждой задачи. который может действовать на основе идентификатора задачи (Некоторое свойство Unquie с заданием) – Mani

+0

Любая идея о том, как будет обозначаться аннотация объекта Scope на классе SubTask? Я имею в виду, как бы вы связали компонент с областью действия задачи с областью задач, которая связана с экземпляром Task, который находится где-то ниже этого объекта с областью действия в иерархии объектов с учетом того, что экземпляр является динамическим? –

1

Я думаю custom scopes то, что вы просите. Тем не менее, некоторые слова осторожности: как правило, больная точка, которую вы описываете, получается из чрезмерно плотно связанного дизайна, а не с законной необходимостью вставать на локти во внутренностях контейнера МОК. Возможно, вы являетесь одним из немногих людей, которые действительно имеют эту законную потребность, но гораздо более вероятно, что редизайн решит вашу проблему гораздо более чистым способом.

+0

Единственный очевидный способ редизайна - заменить модули с привязкой к модулю одиночными точками и искать контекстные данные в этих синглетах, используя уникальные идентификаторы задач в качестве ключей. –

+0

Оптимальный дизайн, к сожалению, редко очевиден, и часто требуется много итераций. Тем не менее, я готов поспорить с хорошими деньгами, что лучшее, что вы могли бы сделать, это рефакторинг. Вероятно, некоторые из этих psuedo-singletons, которые вы можете сделать апатридом и/или разбиты на части, чтобы упростить график зависимости. – Floegipoky

+0

Абстрактная идея этой видимой сложности вращается вокруг довольно простой концепции многоразового компонента, который имеет зависимости, совместно используемые в этом компоненте. Мне интересно, как бы вы разделили двигатель автомобиля на куски, чтобы отодвинуть его от автомобиля, а затем установить его как автономное средство, проводящее его обратно к машине, используя шестерни или что-то подобное :) То, что я действительно пытаюсь избегайте разбивать логическую компонентную абстракцию, чтобы сделать IoC счастливым. Последним средством было бы просто вводить зависимости руками. –

Смежные вопросы