LoginSignup
1
0

More than 1 year has passed since last update.

@Beanと@Qualifierを使ってDIコンテナに設定したクラスを利用してみる

Last updated at Posted at 2023-04-02

今日も備忘録です。

このドキュメントについて

下記4点について記載していきます。

  1. @Beanを利用して、DIコンテナにクラスを設定する方法
  2. 上記で登録したクラスを利用する方法
  3. @Qualifierを利用する必要がある場合について
  4. @Qualifier利用する際の注意点

実行環境

・Java17
・springboot 3.0.2

実装

  1. @Beanを利用して、DIコンテナにクラスを設定する方法
@Configuration
public class ThreadPoolConfig {

    @Bean(name = "Thread1")
    ThreadPoolTaskExecutor configThreadPool() {
        var threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(2);
        threadPool.setMaxPoolSize(5);
        threadPool.setKeepAliveSeconds(0);
        threadPool.setQueueCapacity(500);
        threadPool.setDaemon(true);
        threadPool.setThreadNamePrefix("Thread1-");
        threadPool.initialize();
        return threadPool;
    }

    @Bean(name = "Thread2")
    ThreadPoolTaskExecutor configThreadPool2() {
        var threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(2);
        threadPool.setMaxPoolSize(5);
        threadPool.setKeepAliveSeconds(0);
        threadPool.setQueueCapacity(500);
        threadPool.setDaemon(true);
        threadPool.setThreadNamePrefix("Thread2-");
        threadPool.initialize();
        return threadPool;
    }
}

説明:

  1. BeanをDIコンテナに登録するには、まず@Configurationを設定しする必要がある。
    Spring Bootが起動時にDIコンテナに登録する対象を見つける際に@Configurationをつけたクラスを探してくれます。

  2. @Beanをメソッドに付与して、登録したいクラスをreturnで返却する。
    今回で言うと、threadPoolの設定を行ったThreadPoolTaskExecutorを返却している。

  3. @Beanを付与する際に、name = "" をつけておくと、DIコンテナに登録する名前を決められる。

注意点:
ここで同じクラスを登録する場合、上記のようにname = "" をつけるまたは、@Primaryをつけないと、利用する際にspringがどちらのクラスを利用するのか判断ができなくなるので、アプリケーションの起動ができなくなる。

2.上記で登録したクラスを利用する方法

@Service
@RequiredArgsConstructor
@Slf4j
public class AsyncService {
    private final MailSenderService mailSenderService;
    private final UseThreadPoolTaskTest useThreadPoolTaskTest;

    @Autowired
    @Qualifier("Thread2")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public void useThreadPoolTask(AsyncRequest request, LocalDateTime now) {
        threadPoolTaskExecutor.execute(() -> {
            log.info(Thread.currentThread().getName() + Thread.currentThread().getId());
            try{
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                throw new RuntimeException("割り込み", e);
            }
            log.info("処理1終了");
        });

        threadPoolTaskExecutor.execute(() -> {
            log.info(Thread.currentThread().getName() + Thread.currentThread().getId());
            try{
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                throw new RuntimeException("割り込み", e);
            }
            log.info("処理2終了");
        });

        threadPoolTaskExecutor.execute(() -> {
            IntStream.iterate(0, a -> a+1).limit(10).forEach(b -> log.info(String.valueOf(b)));
            log.info("処理3終了");});

    }
}


説明:

  1. フィールドに記載したThreadPoolTaskExecutorに@Autowiredを利用して依存性を注入。
  2. @Qualifierを付与して、先ほど@Beanに設定したname=""部分を引数に設定する
  3. DIコンテナに登録されたクラスが利用できるようになる

注意点:
1.@RequiredArgsConstructorを利用して依存性を注入しようとして、finalをつけてしまうとコンストラクタにまで@Qualifierが設定されないので、@Autowiredで依存性を注入する。

↑これにハマって時間食ってしまったので、気をつける

まとめ

@Configuration@Beanの組合わせでDIコンテナに登録した後、@Qualifierを利用すると登録したクラスが利用できる。

登録したクラスが単体で被りがないのであれば、@Qualifierを利用せず@RequiredArgsConstructorなどで依存性注入しても問題なく動く。

springの便利な@達なので、どんどん利用していきたいですね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0