【问题标题】:Proper way of autowiring shared queue in Spring在 Spring 中自动装配共享队列的正确方法
【发布时间】:2015-08-03 14:50:58
【问题描述】:

我在我的应用程序中实现了一种生产者-消费者模式。一方面,生产者推动实体处理从不同来源收到的进程,另一方面,我有消费者将这些事件从队列中取出并处理它们。

生产者和消费者都是 spring bean 并且是自动发现的,并且都需要链接到这个共享队列。我知道我可以在 xml 文件或 Java 配置中定义我的 bean,并将此队列作为参数作为构造函数参数或通过 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 配置文件。 Spring 文档页面中的 XML 列表示例:

<util:list id="emails">
    <value>pechorin@hero.org</value>
    <value>raskolnikov@slums.org</value>
    <value>stavrogin@gov.org</value>
    <value>porfiry@gov.org</value>
</util:list>

然后是Java类:

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

有没有办法在 java 配置中创建队列作为此类资源?还是有其他方法可以将共享队列注入不同的 bean?

【问题讨论】:

  • 可能是一个 @Component class ProducerConsumerConfiguration 有一个 getQueue() 方法。但这更多是概念上的差异,仍然是某种包装。

标签: java spring autowired


【解决方案1】:

Don Bottstein 的建议会起作用,你只需要像这样使用它。

@Configuration
public class QueueConfig {

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

然后在 Producer 和 Consumer 类中执行如下操作:

@Component
public class Producer {

    @Autowired
    private QueueConfig queueConfig;

    public void produceMyObject(MyObject myObject) {
        queueConfig.blockingQueue.put(myObject);
    }
}

【讨论】:

    【解决方案2】:

    基本上,您将定义一个 @Configuration 注释类来注册给定类型的 bean。例如,

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

    bean 名称默认为方法的名称(本例中为sharedQueue),或者您可以覆盖注解中的名称(@Bean(name="someName"))。默认作用域是单例,可以在方法上使用@Scope(...)进行更改。

    @Configuration 类在组件扫描期间被拾取,就像 @Component 带注释的类一样。

    但是,正如您所说明的那样,我认为使用包装类没有任何问题。事实上,使用包装器类可以让您更轻松地在未来的实现中添加适应。

    【讨论】:

    • 其实这个解决方案是行不通的。我有以下异常 - NoSuchBeanDefinitionException: No qualifying bean of type [com.example.MyObject] found for dependency [collection of com.example.MyObject]
    • 我对包装器非常满意,但我认为应该有更优雅的解决方案
    猜你喜欢
    • 1970-01-01
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 2013-03-08
    • 2015-12-27
    • 1970-01-01
    相关资源
    最近更新 更多