2017-03-08 106 views
1

我想更好地理解如何在我的應用程序中實現構造函數注入。我有一些由SimpleMessageListenerContainer工作者執行的後臺進程,它們將消息從AMQP服務器中提取出來。SimpleMessageListenerContainer中的構造函數注入

我的應用程序包含服務層和回購層,工作人員使用服務進行數據讀取/寫入。我的控制器,服務和倉庫都是使用構造函數注入來設置的,但是因爲需要實例化新版本的工人,所以我不知道如何初始化工人。

工人

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; 
    } 
} 

由於我的工人要求UserService,我必須在我初始化提供了這樣的一個實例在WorkerConfig新的RandomWorker。那麼,我將不得不爲所有工作人員使用的EVERY服務創建一個@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

如果您將它們指定爲bean方法的參數,Spring將自動注入依賴項。在你的情況,你只需要修改你的工人豆方法:

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

如果UserService服務上下文可用,Spring會自動注入它作爲userService參數。您不需要爲每個服務使用@Bean方法 - 在上下文中註冊bean的任何方法都可以使用(例如@ComponentScan,@SpringBootApplication或者甚至手動將bean添加到上下文中)。如果使用構造函數或setter注入無關緊要。

作爲一個方面說明 - 構造函數注入更好,因爲你可以確定你的對象總是以有效狀態實例化。一直以來,所有對象始終處於有效狀態通常是一個很好的設計。

+0

感謝您的建議!當我嘗試實現這一點時,Spring會抱怨「沒有發現'UserService'類型的bean」。這是否意味着我的服務在上下文中不可用? 此外,我將如何修改我的randomWorkerContainer()方法,它調用randomWorker()Bean來啓動一個新的工作?這些服務是否也會被注入? –

+0

是的,這意味着用戶服務在上下文中不可用。您可以用'@ Service'註釋用戶服務類並將'@ ComponentScan'添加到'@ Configuration'配置類中。至於randomWorkerContainer - 只需將RandomWorker類型的paramarter添加到容器Bean方法。 –

+0

太棒了!我在錯誤的文件中有我的@ComponentScan。現在一切正常,謝謝! –