简体   繁体   English

将初始化代码添加到 Spring 引导应用程序的正确方法是什么?

[英]What's the proper way to add initialization code to a Spring Boot application?

TLDR: I want my Spring Boot application to run some initialization code when it starts. TLDR:我希望我的 Spring 引导应用程序在启动时运行一些初始化代码。 The code needs access to Spring beans and values.代码需要访问 Spring bean 和值。

I'm writing a Spring Boot application that will consume multiple messages from a queue concurrently.我正在编写一个 Spring 引导应用程序,它将同时使用队列中的多条消息。 In order to do this, it needs to instantiate multiple consumer objects.为此,它需要实例化多个消费者对象。 Does Spring have a good way to instantiate a configurable number of instances of the same class? Spring 是否有一种很好的方法来实例化相同 class 的可配置数量的实例?

The queue client I have to use acts as a thread pool.我必须使用的队列客户端充当线程池。 It creates one thread for every consumer object I give it.它为我给它的每个消费者 object 创建一个线程。 The consumer objects only receive one message at a time, and they have to fully process and acknowledge the message before they can receive another one.消费者对象一次只接收一条消息,他们必须完全处理并确认该消息,然后才能接收另一条消息。 The consumers aren't thread-safe, so I can't just use a singleton instance.消费者不是线程安全的,所以我不能只使用 singleton 实例。

I considered the approach below, but it doesn't feel right to me.我考虑了下面的方法,但对我来说感觉不对。 It seems like an abuse of the @Component annotation because the Initializer instance isn't used after it's constructed.这似乎是对@Component注释的滥用,因为Initializer实例在构造后未使用。 What's a better way to do it?有什么更好的方法呢?

@Component
public class Initializer {

    public Initializer(ConsumerRegistry registry, @Value("${consumerCount}") int consumerCount) {
        for (int i = 0; i < consumerCount; i++) {
            // Each registered consumer results in a thread that consumes messages.
            // Incoming messages will be delivered to any consumer thread that's not busy.
            registry.registerConsumer(new Consumer());
        }
    }

}

An ApplicationListener would fit your need. ApplicationListener将满足您的需要。 It gets notified on the registered event eg when the ApplicationContext is ready.它会在注册的事件上得到通知,例如当 ApplicationContext 准备好时。 You will have full access to all your Beans and injection.您将拥有对所有 Bean 和注入的完全访问权限。

@Component
public class StartupApplicationListener implements ApplicationListener<ApplicationReadyEvent> {

    @Inject
    private ConsumerRegistry registry;

    @Inject
    @Value("${consumerCount}")
    private int consumerCount;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        //do your logic
        for (int i = 0; i < consumerCount; i++) {
            // Each registered consumer results in a thread that consumes messages.
            // Incoming messages will be delivered to any consumer thread that's not busy.
            registry.registerConsumer(new Consumer());
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM