来自非bean类的spring访问代理bean

时间:2018-07-10 12:55:21

标签: java spring spring-boot metrics codahale-metrics

我有一个Spring bean,它在其方法上使用dropwizard-metrics注释来度量某些度量(请参阅#parse方法):

re

如您所见,这个bean向执行者服务提交了一个新任务,该任务不是bean,但是需要引用 Consumer bean来重用其逻辑(请参见 consumer。 parse(record); 调用):

@Component
public class Consumer extends AbstractConsumer {

  @Autowired
  private EventsService eventsService;

  private ExecutorService executor;

  @PostConstruct
  void init() throws Exception {
    executor = Executors.newFixedThreadPool(1);

    ConsumerEventsHandler consumer = new ConsumerEventsHandler(Arrays.asList("topic1"), this);
    executor.submit(consumer);
  }

  @Timed(name = CONSUMER_BATCH_PARSING_TIME, absolute = true)
  public void parse(ConsumerRecord<String, String> record) {
    String val = record.value();
    eventsService.parseToDB(val);
  }
}

这是指标配置(我使用“ ryantenney / metrics-spring”库):

public class ConsumerEventsHandler implements Runnable {

private Consumer consumer;
private List<String> topics;
protected final KafkaConsumer<String, String> kafkaConsumer;

public ConsumerEventsHandler(List<String> topics, Consumer consumer) {
    this.topics = topics;
    this.consumer = consumer;
    this.kafkaConsumer = new KafkaConsumer<>();
}

@Override
public void run() {
    try {
        consumer.subscribe(topics);
        while (true) {
            ConsumerRecords<String, String> records = consumer.poll(Long.MAX_VALUE);

            for (ConsumerRecord<String, String> record : records) {
                consumer.parse(record);
            }
        }
    } finally {
        consumer.close();
    }
}

}

结果,我看到 Consumer bean被代理,但是 ConsumerEventsHandler 包含对普通bean的引用,原因是它是在 Consumer的通过'new ConsumerEventsHandler(..)' Consumer bean的@PostConstruct方法尚未被代理,我认为@PostConstruct是在进行处理之前调用的。

我看到的唯一解决方法是每次在#run方法内通过ApplicationContext#getBean获取 Consumer bean引用,而不是将引用存储在 ConsumerEventsHandler 类变量中。 还有其他解决方案吗?

1 个答案:

答案 0 :(得分:1)

只需在非春季课程上创建一个静态

public class ConsumerEventsHandler implements Runnable {

private static Consumer consumer;
private List<String> topics;
protected final KafkaConsumer<String, String> kafkaConsumer;

public ConsumerEventsHandler(List<String> topics) {
    this.topics = topics;
    this.kafkaConsumer = new KafkaConsumer<>();
}

public static setConsumer(Consumer consumer) {
    ConsumerEventsHandler.consumer = consumer;
}

然后在您的春天那边,您可以:

  @PostConstruct()
  public void init() {
    configureReporters(registry);
    ConsumerEventsHandler.setConsumer(consumer);
  }