Spring Framework Tips: DIコンテナとJavaConfig周り
- 2025/1/23
- ナレッジ, ブログ
- Java, Spring Boot, Spring Framework
- Comments Off on Spring Framework Tips: DIコンテナとJavaConfig周り
イントロダクション
Spring FrameworkのDI(Dependency Injection)コンテナは、依存性の管理を自動化し、コードの結合度を下げる強力なツールです。本記事では、DIコンテナやJavaConfig、Beanの定義方法、環境ごとの設定を切り替えるプロファイル活用法までをまとめました。
DIコンテナ
DIコンテナの役割
DIのためのBeanオブジェクトの生成と管理を行う。依存性の注入を自動化し、結合度を下げる。
DIコンテナの生成方法
以下の方法でDIコンテナ生成できる。
public static void main(String[] args) {
// FooConfigはJavaConfigクラス。
ApplicationContext context = new AnnotationConfigApplicationContext(FooConfig.class);
}
SpringBootを使う場合は、runメソッドで生成される。
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(FooApplication.class, args);
}
DIコンテナからBeanオブジェクトを取得
ApplicationContext context = SpringApplication.run(FooApplication.class, args);
FooService fooService = context.getBean(FooService.class);
...
JavaConfig
JavaConfigの役割
DIコンテナに読み込ませるコンフィグレーションファイル。
JavaConfigの定義方法
@Configアノテーションを付与したJavaクラスで定義する。@Beanをメソッドに付与してBeanを定義可能。
@Configuration
public class FooConfig {
// FooServiceのオブジェクトを生成し、Beanとして管理する
@Bean
public FooService fooService(){
...
}
}
複数のJavaConfigクラスを読み込む方法
以下の方法で複数のJavaConfigクラスを読み込み可能。
- AnnotationConfigApplicationContextクラスのコンストラクタで複数指定
- @Importアノテーションを用いる
- コンポーネントスキャンを用いる
AnnotationConfigApplicationContextクラスのコンストラクタで複数指定
ApplicationContext context = new AnnotationConfigApplicationContext(FooConfig.class, BarConfig.class);
@Importアノテーションを用いて複数指定
@Configuration
@Import(BarConfig.class)
public class FooConfig{
...
}
@Configuration
public class BarConfig{
...
}
ApplicationContext context = new AnnotationConfigApplicationContext(FooConfig.class);
コンポーネントスキャンを用いて複数指定
@Configuration
@ComponentScan
public class FooConfig{
...
}
@Configuration
public class BarConfig{
...
}
ApplicationContext context = new AnnotationConfigApplicationContext(FooConfig.class);
Bean
Bean定義方法
以下の方法で定義可能。
- ステレオタイプアノテーション(@Component、@Serviceなど)
- JavaConfigにおける@Beanアノテーション
- XMLファイル(レガシーシステム向け)
ステレオタイプアノテーションによるBean定義
Beanとして管理したい具象クラス付与するアノテーションをステレオタイプアノテーションという。決められたいずれかのアノテーションを付与すると、Springが具象クラスのコンストラクタを呼び出してオブジェクトを生成し、Beanとして管理する。
@Service
public class FooServiceImpl implements FooService{
...
}
主なステレオタイプアノテーションの種類
@Service
Serviceの具象クラスに付与。付加機能なし。
@Repository
Repositoryの具象クラスに付与。付加機能として、データベースアクセス周りの例外がSpringが提供する例外に変換されるようになる。
@Controller
Controllerの具象クラスに付与。付加機能として、Spring MVCの機能を利用可能になる。
@Component
汎用的なステレオタイプアノテーション。上記に当てはまらないクラスに用いることが多い。付加機能なし。
JavaConfigの@BeanアノテーションによるBean定義
JavaConfigクラス上で@Beanアノテーションを用いてBeanを定義することもできる。
@Configuration
public class FooConfig {
@Bean
public FooService fooService(FooRepository repository){
return new FooServiceImpl(repository);
}
@Bean
public FooRepository fooRepository(){
return new JdbcFooRepository();
}
}
Bean定義方法の使い分け
定義方法 | 利点 | 用途 |
---|---|---|
ステレオタイプアノテーション | 簡単に定義可能。コード内で明示的に宣言。 | 自作クラスでの使用が適している |
JavaConfig | 柔軟性が高い。外部ライブラリのクラスも定義可能。 | 外部ライブラリのBeanを登録する場合 |
XML | 古いシステムで使用されている可能性あり。 | レガシーシステム対応 |
外部ライブラリをBean管理したい場合はJavaConfigでの@Bean定義を利用するのが良い。
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("username");
config.setPassword("password");
config.setMaximumPoolSize(10);
return new HikariDataSource(config);
}
Beanのインジェクション方法
Beanオブジェクトをインジェクションするには以下の方法がある。
- コンストラクタでのインジェクション
- フィールドでのインジェクション
- JavaConfigでの@Beanメソッド内での記述
コンストラクタでのインジェクション
コンストラクタの引数として依存オブジェクトを受け取る方法。DIコンテナがコンストラクタを呼び出す際に、引数の型に合うBeanのオブジェクトを渡してくれる。
@Service
public class FooService {
private final FooRepository fooRepository;
// コンストラクタが一つしかない場合は、@Autowiredアノテーション省略可
@Autowired
public FooService(FooRepository fooRepository) {
this.fooRepository = fooRepository;
}
}
フィールドでのインジェクション
フィールドに直接@Autowiredアノテーションを付ける方法。
@Service
public class FooService {
@Autowired
private FooRepository fooRepository;
...
}
テスト容易性や、フィールドをfinal修飾できることなどいくつかの利点から、コンストラクタでのインジェクションが推奨。
JavaConfigでの@Beanメソッド内での記述
fooServiceメソッドの引数でFooRepository型の引数を定義しておくと、FooServiceの@Beanメソッドを呼び出す際に、引数のFooRepositoryのBeanオブジェクトをDIコンテナから探してきて引数に渡してくれる。これによりServiceImplオブジェクトにJdbcFooRepositoryオブジェクトがインジェクションされる。
@Configuration
public class FooConfig {
@Bean
public FooService fooService(FooRepository repository){
return new FooServiceImpl(repository);
}
@Bean
public FooRepository fooRepository(){
return new JdbcFooRepository();
}
}
プロファイルによるコンフィグレーションの切り替え
環境(開発、テスト、本番など)に応じて異なる設定を適用するための機能。@Profileアノテーションを利用して、DIコンテナ生成時に有効にするBeanやコンフィグレーションを切り替えられる。
プロファイル指定方法
@Profileアノテーションを用いて、環境ごとにグルーピングできる
@Repository
@Profile("prd")
public class ExternalFooRepository() implements FooRepository{
...
}
@Repository
@Profile("stg")
public class JdbcFooRepository() implements FooRepository{
...
}
@Service
public class FooService() implements FooService{
...
}
JavaConfigクラスに@Profileを付与
@Profile("prd")
@Configuration
@ComponentScan
public class FooConfig{
@Bean
public FooService fooService(){
...
}
Beanごとに指定
@Configuration
@ComponentScan
public class FooConfig{
@Bean
@Profile("prd")
public FooService fooService(){
...
}
プロファイルの指定方法
- 起動時の引数で指定:
java -Dspring.profiles.active=prd -jar myapp.jar
- 環境変数で指定:
export SPRING_PROFILES_ACTIVE=stg
- Spring Bootではapplication.propertiesで指定可能。
この情報は役に立ちましたか?