SimpleMessageListenerContainer 中的构造函数注入

Constructor Injection in SimpleMessageListenerContainer

我试图更好地了解如何在我的应用程序中实现构造函数注入。我有一些由 SimpleMessageListenerContainer worker 执行的后台进程,它们从 AMQP 服务器中提取消息。

我的应用程序包含一个服务层和一个 repo 层,一个工作人员使用这些服务来获取数据 reads/writes。我的控制器、服务和 repos 都是使用构造函数注入设置的,但是由于需要实例化新版本的 worker,所以我一直在研究如何初始化 worker。

工人

public class RandomWorker extends Worker {

    private UserService userService;

    @Autowired
    public RandomWorker(UserService userService) {
        this.userService = userService;
    }

    @Override
    public byte[] handleMessage(byte[] message) {
        ... do work ...
    }
}

服务层

@Service
public class UserService {

    private SecurityAreaRepo securityAreaRepo;
    private SecurityRoleRepo securityRoleRepo;
    private UserRepo userRepo;

    @Autowired
    public UserService(SecurityAreaRepo securityAreaRepo,
                       SecurityRoleRepo securityRoleRepo,
                       UserRepo userComponent) {
        this.securityAreaRepo = securityAreaRepo;
        this.securityRoleRepo = securityRoleRepo;
        this.userRepo = userRepo;
    }
}

WorkerConfig

@Configuration
public class WorkerConfig {

    @Bean
    public RandomWorker randomWorker() {
        return new RandomWorker();
    }

    @Bean(name="randomWorkerContainer")
    public SimpleMessageListenerContainer randomWorkerContainer() {
        SimpleMessageListenerContainer smlc = new SimpleMessageListenerContainer();
        smlc.setConnectionFactory(connectionFactory());
        smlc.setMessageListener(new MessageListenerAdapter(randomWorker(), "handleMessage"));
        smlc.setQueueNames("random.worker.queue");
        smlc.setConcurrentConsumers(5);
        smlc.start();
        return smlc;
    }
}

由于我的 worker 需要 UserService,因此我必须在初始化新的 RandomWorker 时在 WorkerConfig 中提供一个实例。那么我是否必须为所有工作人员使用的每项服务创建一个@Bean?我的 WorkerConfig 看起来像这样:

@Configuration
public class WorkerConfig {
    @Bean
    public UserService userService() {
        return new UserService(new SecurityAreaRepo(), new SecurityRoleRepo(), new UserRepo());
    }

    @Bean
    public RandomWorker randomWorker() {
        return new RandomWorker(userService());
    }

    @Bean(name="randomWorkerContainer")
    public SimpleMessageListenerContainer randomWorkerContainer() {
        SimpleMessageListenerContainer smlc = new SimpleMessageListenerContainer();
        smlc.setConnectionFactory(connectionFactory());
        smlc.setMessageListener(new MessageListenerAdapter(randomWorker(), "handleMessage"));
        smlc.setQueueNames("random.worker.queue");
        smlc.setConcurrentConsumers(5);
        smlc.start();
        return smlc;
    }
}

如果是这种情况,我只是不明白构造函数注入的意义,因为字段注入使一切变得如此简单。有人可以阐明这一点吗?

如果您将依赖项指定为 bean 方法的参数,

Spring 会自动注入依赖项。在你的情况下,你只需要将你的工作 bean 方法修改为:

@Bean
public RandomWorker randomWorker(UserService userService) {
    return new RandomWorker(userService);
}

如果 UserService 服务在上下文中可用,Spring 将自动将其作为 userService 参数注入。您不需要为每个服务使用 @Bean 方法 - 任何在上下文中注册 bean 的方法都可以使用(例如 @ComponentScan、@SpringBootApplication 甚至手动将 bean 添加到上下文)。使用构造函数或 setter 注入都没有关系。

附带说明 - 构造函数注入更好,因为您可以确保您的对象始终在有效状态下实例化。将所有对象始终保持在有效状态通常是一个很好的设计。