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 注入都没有关系。
附带说明 - 构造函数注入更好,因为您可以确保您的对象始终在有效状态下实例化。将所有对象始终保持在有效状态通常是一个很好的设计。
我试图更好地了解如何在我的应用程序中实现构造函数注入。我有一些由 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;
}
}
如果是这种情况,我只是不明白构造函数注入的意义,因为字段注入使一切变得如此简单。有人可以阐明这一点吗?
Spring 会自动注入依赖项。在你的情况下,你只需要将你的工作 bean 方法修改为:
@Bean
public RandomWorker randomWorker(UserService userService) {
return new RandomWorker(userService);
}
如果 UserService
服务在上下文中可用,Spring 将自动将其作为 userService
参数注入。您不需要为每个服务使用 @Bean
方法 - 任何在上下文中注册 bean 的方法都可以使用(例如 @ComponentScan、@SpringBootApplication 甚至手动将 bean 添加到上下文)。使用构造函数或 setter 注入都没有关系。
附带说明 - 构造函数注入更好,因为您可以确保您的对象始终在有效状态下实例化。将所有对象始终保持在有效状态通常是一个很好的设计。