2017-03-08 4 views
1

私のアプリケーションでコンストラクタインジェクションを実装する方法をよりよく理解しようとしています。 SimpleMessageListenerContainerワーカーによって実行されるいくつかのバックグラウンドプロセスがあり、AMQPサーバーからメッセージを引き出します。SimpleMessageListenerContainerのコンストラクタインジェクション

私のアプリケーションにはサービスレイヤーとレポレイヤーが含まれているため、ワーカーはデータの読み書きにサービスを使用します。コントローラ、サービス、リポジトリはすべてコンストラクタインジェクションを使用してセットアップされていますが、新しいバージョンの作業者をインスタンス化する必要があるため、作業者を初期化する方法について固執しています。

私の労働者がUserServiceのを必要とするので、私は初期化時に、私は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; 
    } 
} 

ワーカー

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新しいRandomWorker。だから私はすべての労働者が使うすべてのサービスの@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

Springは、Beanメソッドの引数として指定すると、依存関係を自動的に挿入します。あなたのケースでは、あなただけにあなたのワーカーBeanメソッドを変更する必要があります。UserServiceサービスがコンテキストで使用可能な場合

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

、春には、自動的にuserServiceパラメータとして、それを注入します。すべてのサービスに@Beanのメソッドを使用する必要はありません。コンテキストでBeanを登録する方法(@ComponentScan、@SpringBootApplication、または手動でBeanをコンテキストに追加するなど)が有効です。コンストラクタまたはセッタ注入を使用するかどうかは関係ありません。

オブジェクトが常に有効な状態でインスタンス化されていることを確認できるので、コンストラクタインジェクションが優れています。一般に、すべてのオブジェクトを常に有効な状態に保つことは良い設計です。

+0

お寄せいただきありがとうございます!これを実装しようとすると、Springは「UserServiceタイプのBeanは見つかりませんでした」と苦情を言います。これは私のサービスが文脈で利用できないことを意味しますか? さらに、randomWorker()Beanを呼び出したrandomWorkerContainer()メソッドを変更して、新しいワーカーを起動させる方法はありますか?サービスはそれにも注入されますか? –

+0

はい、これは、コンテキストでユーザーサービスが利用できないことを意味します。あなたは '@ Service'でユーザサービスクラスに注釈を付け、' @Configuration'設定クラスに '@ ComponentScan'を追加することができます。 randomWorkerContainerについては、コンテナのbeanメソッドにRandomWorker型のparamarterを追加するだけです。 –

+0

恐ろしい!間違ったファイルに@ComponentScanがありました。すべてが今、完璧に動作します、ありがとう! –

関連する問題