2015-08-03 2 views
3

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

Оба производителя и потребителя являются пружинными бобами и автоматически обнаруживаются, и оба требуют связи с этой общей очередью. Я знаю, что я могу определить свои компоненты в файле xml или конфигурации Java и передать эту очередь как параметр в качестве аргумента конструктора или через setter, но есть способ импортировать его автоматически. Единственная идея приходит мне на ум, чтобы создать оболочку для этой очереди, а затем вводит эту обертку вместо:

@Component 
public class QueueWrapper { 
    private final BlockingQueue<MyObject> sharedQueue = new LinkedBlockingQueue<>(); 

    public void put(MyObject toPut) { 
     sharedQueue.put(toPut); 
    } 

    public MyObject take() { 
     return sharedQueue.take(); 
    } 
} 

@Component 
public class Producer { 
    @Autowire 
    private QueueWrapper queue; 
    .... 
} 


@Component 
public class Consumer { 
    @Autowire 
    private QueueWrapper queue; 
    .... 
} 

ли стоит создать эту обертку? Я знаю аннотацию @Resource, но я использовал ее только со списками, картами и наборами и фактически не знаю, как настроить конфигурационный файл конфигурации Java. XML пример списка со страницы Спринг документации:

<util:list id="emails"> 
    <value>[email protected]</value> 
    <value>[email protected]</value> 
    <value>[email protected]</value> 
    <value>[email protected]</value> 
</util:list> 

А потом Java класс:

@Component 
public class SomeClass { 
    @Resource(name="emails") 
    private List<String> emails; 
} 

Есть ли способ, чтобы создать очередь как такой ресурс в конфигурации Java? Или есть ли другие способы вставить общую очередь в разные бобы?

+0

Может быть '@Component класса ProducerConsumerConfiguration', который имеет getQueue)' метод '(. Но это скорее концептуальная разница, но все-таки оболочка. – zapl

ответ

1

В принципе, вы бы определили аннотированный класс @Configuration для регистрации компонента данного типа. НАПРИМЕР,

@Configuration 
public class AppConfig { 
    @Bean 
    public BlockingQueue<MyObject> sharedQueue() { 
     return new LinkedBlockingQueue<>(); 
    } 
} 

от имени боб по умолчанию имя метода (sharedQueue в данном случае), или вы можете изменить имя в аннотации (@Bean(name="someName")). Область по умолчанию - singleton, которая может быть изменена с помощью метода @Scope(...).

@Configuration классы подбираются во время сканирования компонентов точно так же, как @Component аннотированных классов.

Однако я не вижу ничего плохого в использовании класса-оболочки, как вы показали. Действительно, использование класса-оболочки позволит вам более легко добавить адаптацию к реализации в будущем.

+0

На самом деле это решение не работает. У меня есть следующее исключение: «NoSuchBeanDefinitionException: не существует подходящего компонента типа [com.example.MyObject], найденного для зависимости [коллекция com.example.MyObject]' –

+0

Я отлично разбираюсь в оболочке, но я думаю, что там должно быть более элегантным решением –

4

Предлагаемый Дон Ботштейн будет работать, вам просто нужно использовать его так.

@Configuration 
public class QueueConfig { 

    @Bean 
    public BlockingQueue<MyObject> blockingQueue() { 
     return new LinkedBlockingQueue<>(); 
    } 
} 

Тогда в классе производителей и потребителей сделать что-то вроде этого:

@Component 
public class Producer { 

    @Autowired 
    private QueueConfig queueConfig; 

    public void produceMyObject(MyObject myObject) { 
     queueConfig.blockingQueue.put(myObject); 
    } 
} 
Смежные вопросы