今日も備忘録です。
このドキュメントについて
下記4点について記載していきます。
- @Beanを利用して、DIコンテナにクラスを設定する方法
- 上記で登録したクラスを利用する方法
- @Qualifierを利用する必要がある場合について
- @Qualifier利用する際の注意点
実行環境
・Java17
・springboot 3.0.2
実装
- @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;
}
}
説明:
-
BeanをDIコンテナに登録するには、まず@Configurationを設定しする必要がある。
Spring Bootが起動時にDIコンテナに登録する対象を見つける際に@Configurationをつけたクラスを探してくれます。 -
@Beanをメソッドに付与して、登録したいクラスをreturnで返却する。
今回で言うと、threadPoolの設定を行ったThreadPoolTaskExecutorを返却している。 -
@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終了");});
}
}
説明:
- フィールドに記載したThreadPoolTaskExecutorに@Autowiredを利用して依存性を注入。
- @Qualifierを付与して、先ほど@Beanに設定したname=""部分を引数に設定する
- DIコンテナに登録されたクラスが利用できるようになる
注意点:
1.@RequiredArgsConstructorを利用して依存性を注入しようとして、finalをつけてしまうとコンストラクタにまで@Qualifierが設定されないので、@Autowiredで依存性を注入する。
↑これにハマって時間食ってしまったので、気をつける
まとめ
@Configurationと@Beanの組合わせでDIコンテナに登録した後、@Qualifierを利用すると登録したクラスが利用できる。
登録したクラスが単体で被りがないのであれば、@Qualifierを利用せず@RequiredArgsConstructorなどで依存性注入しても問題なく動く。
springの便利な@達なので、どんどん利用していきたいですね。