@Bean
アノテーションの使用
@Bean
は、メソッドレベルのアノテーションであり、XML <bean/>
要素の直接の類似物です。アノテーションは、次のような <bean/>
によって提供される属性の一部をサポートします。
@Bean
アノテーションは、@Configuration
アノテーション付きまたは @Component
アノテーション付きクラスで使用できます。
Bean の宣言
Bean を宣言するために、@Bean
アノテーションを使用してメソッドにアノテーションを付けることができます。このメソッドを使用して、メソッドの戻り値として指定された型の ApplicationContext
内に Bean 定義を登録します。デフォルトでは、Bean 名はメソッド名と同じです。次の例は、@Bean
メソッドの宣言を示しています。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
@Configuration
class AppConfig {
@Bean
fun transferService() = TransferServiceImpl()
}
上記の構成は、次の Spring XML とまったく同じです。
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
次のテキストイメージに示すように、両方の宣言により、transferService
という名前の Bean が ApplicationContext
で使用可能になり、型 TransferServiceImpl
のオブジェクトインスタンスにバインドされます。
transferService -> com.acme.TransferServiceImpl
デフォルトのメソッドを使用して Bean を定義することもできます。これにより、デフォルトのメソッドで Bean 定義を使用してインターフェースを実装することにより、Bean 構成を構成できます。
Java
public interface BaseConfig {
@Bean
default TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
@Configuration
public class AppConfig implements BaseConfig {
}
次の例に示すように、@Bean
メソッドをインターフェース(または基本クラス)戻り値の型で宣言することもできます。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
@Configuration
class AppConfig {
@Bean
fun transferService(): TransferService {
return TransferServiceImpl()
}
}
ただし、これにより、事前型予測の可視性が指定されたインターフェース型(TransferService
)に制限されます。次に、影響を受けるシングルトン Bean がインスタンス化された後でのみ、コンテナーに認識されるフル型(TransferServiceImpl
)を使用します。遅延のないシングルトン Bean は宣言順序に従ってインスタンス化されるため、別のコンポーネントが宣言されていない型(transferService
Bean がインスタンス化された後にのみ解決される @Autowired TransferServiceImpl
など)によって一致しようとするタイミングに応じて、異なる型一致結果が表示される場合があります)。
宣言されたサービスインターフェースで型を一貫して参照する場合、@Bean 戻り型はその設計決定に安全に参加できます。ただし、複数のインターフェースを実装するコンポーネント、または実装型で潜在的に参照されるコンポーネントの場合、可能な限り最も具体的な戻り値の型を宣言する方が安全です(少なくとも Bean を参照するインジェクションポイントで要求される特定の)。 |
Bean の依存関係
@Bean
アノテーション付きメソッドは、その Bean を構築するために必要な依存関係を記述する任意の数のパラメーターを持つことができます。たとえば、TransferService
に AccountRepository
が必要な場合、次の例に示すように、メソッドパラメーターを使用してその依存関係を具体化できます。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
class AppConfig {
@Bean
fun transferService(accountRepository: AccountRepository): TransferService {
return TransferServiceImpl(accountRepository)
}
}
解決メカニズムはコンストラクターベースの依存性注入とほぼ同じです。詳細については、関連するセクションを参照してください。
ライフサイクルコールバックの受信
@Bean
アノテーションで定義されたクラスは、通常のライフサイクルコールバックをサポートし、JSR-250 の @PostConstruct
および @PreDestroy
アノテーションを使用できます。詳細については、JSR-250 アノテーションを参照してください。
通常の Spring ライフサイクルコールバックも完全にサポートされています。Bean が InitializingBean
、DisposableBean
、Lifecycle
を実装している場合、それぞれのメソッドはコンテナーによって呼び出されます。
*Aware
インターフェースの標準セット(BeanFactoryAware、BeanNameAware、MessageSourceAware、ApplicationContextAware など)も完全にサポートされています。
@Bean
アノテーションは、Spring XML の init-method
属性や destroy-method
属性と同様に、任意の初期化および破棄コールバックメソッドを bean
要素に指定することをサポートします。次に例を示します。
Java
Kotlin
public class BeanOne {
public void init() {
// initialization logic
}
}
public class BeanTwo {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public BeanOne beanOne() {
return new BeanOne();
}
@Bean(destroyMethod = "cleanup")
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
class BeanOne {
fun init() {
// initialization logic
}
}
class BeanTwo {
fun cleanup() {
// destruction logic
}
}
@Configuration
class AppConfig {
@Bean(initMethod = "init")
fun beanOne() = BeanOne()
@Bean(destroyMethod = "cleanup")
fun beanTwo() = BeanTwo()
}
デフォルトでは、パブリック そのライフサイクルはアプリケーションの外部で管理されるため、JNDI で取得するリソースに対してデフォルトでそれを行うことができます。特に、Jakarta EE アプリケーションサーバーでは問題があることが知られているため、必ず 次の例は、
また、 |
前の例の上の例の BeanOne
の場合、次の例に示すように、構築中に init()
メソッドを直接呼び出すことも同様に有効です。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean
public BeanOne beanOne() {
BeanOne beanOne = new BeanOne();
beanOne.init();
return beanOne;
}
// ...
}
@Configuration
class AppConfig {
@Bean
fun beanOne() = BeanOne().apply {
init()
}
// ...
}
Java で直接作業する場合、オブジェクトを使用して好きなことを行うことができ、常にコンテナーのライフサイクルに依存する必要はありません。 |
Bean スコープの指定
Spring には @Scope
アノテーションが含まれているため、Bean のスコープを指定できます。
@Scope
アノテーションの使用
@Bean
アノテーションで定義された Bean に特定のスコープが必要であることを指定できます。Bean スコープセクションで指定された標準スコープのいずれかを使用できます。
デフォルトのスコープは singleton
ですが、次の例に示すように、@Scope
アノテーションでこれをオーバーライドできます。
Java
Kotlin
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Encryptor encryptor() {
// ...
}
}
@Configuration
class MyConfiguration {
@Bean
@Scope("prototype")
fun encryptor(): Encryptor {
// ...
}
}
@Scope
および scoped-proxy
Spring は、スコープ付きプロキシを介してスコープ付き依存関係を操作する便利な方法を提供します。XML 構成を使用するときにこのようなプロキシを作成する最も簡単な方法は、<aop:scoped-proxy/>
要素です。@Scope
アノテーションを使用して Java で Bean を構成すると、proxyMode
属性と同等のサポートが提供されます。デフォルトは ScopedProxyMode.DEFAULT
です。これは通常、コンポーネントスキャン命令レベルで別のデフォルトが設定されていない限り、スコーププロキシを作成しないことを示します。ScopedProxyMode.TARGET_CLASS
、ScopedProxyMode.INTERFACES
、ScopedProxyMode.NO
を指定できます。
Java を使用して、XML リファレンスドキュメント ( 「スコープ付きプロキシ」を参照) からスコープ付きプロキシの例を @Bean
に移植すると、次のようになります。
Java
Kotlin
// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
return new UserPreferences();
}
@Bean
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
service.setUserPreferences(userPreferences());
return service;
}
// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
fun userPreferences() = UserPreferences()
@Bean
fun userService(): Service {
return SimpleUserService().apply {
// a reference to the proxied userPreferences bean
setUserPreferences(userPreferences())
}
}
Bean 命名のカスタマイズ
デフォルトでは、構成クラスは @Bean
メソッドの名前を結果の Bean の名前として使用します。ただし、次の例に示すように、この機能は name
属性でオーバーライドできます。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean("myThing")
public Thing thing() {
return new Thing();
}
}
@Configuration
class AppConfig {
@Bean("myThing")
fun thing() = Thing()
}
Bean エイリアス
Bean の命名で説明したように、単一の Bean に複数の名前(別名 Bean エイリアス)を付けることが望ましい場合があります。@Bean
アノテーションの name
属性は、この目的のためにストリング配列を受け入れます。次の例は、Bean に複数のエイリアスを設定する方法を示しています。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
}
@Configuration
class AppConfig {
@Bean("dataSource", "subsystemA-dataSource", "subsystemB-dataSource")
fun dataSource(): DataSource {
// instantiate, configure and return DataSource bean...
}
}
Bean の説明
時々、Bean のより詳細なテキスト記述を提供すると役立つことがあります。これは、監視目的で Bean が(おそらく JMX を介して)公開されている場合に特に役立ちます。
@Bean
に説明を追加するには、次の例に示すように、@Description
(Javadoc) アノテーションを使用できます。
Java
Kotlin
@Configuration
public class AppConfig {
@Bean
@Description("Provides a basic example of a bean")
public Thing thing() {
return new Thing();
}
}
@Configuration
class AppConfig {
@Bean
@Description("Provides a basic example of a bean")
fun thing() = Thing()
}