SimpleMessageListenerContainer中的构造函数注入

时间:2017-03-08 22:08:11

标签: java spring dependency-injection constructor-injection

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

我的应用程序包含服务层和repo层,worker使用服务进行数据读/写。我的控制器,服务和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;
    }
}

如果是这种情况,我只是没有看到构造函数注入的重点,当字段注入使一切变得如此简单。有人可以对此有所了解吗?

1 个答案:

答案 0 :(得分:1)

如果将bean指定为bean方法的参数,则Spring会自动注入依赖项。在您的情况下,您只需要将您的工作bean方法修改为:

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

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

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