【まとめ】Springフレームワークにおける Bean の ライフサイクル
今後も情報が分かり次第、随時このページに情報を追加していきます!
この記事では、Spring フレームワークにおける、Java Beanのライフサイクルについてまとめます。
ここに示す内容は、Spring Boot アプリケーションにも当てはまります。
基本、こちらのページを日本語訳しつつ、少しだけ情報を付け加えています。
howtodoinjava.com
1. Bean のライフサイクル
SpringのDIコンテナ(≒IoCコンテナ)が起動すると、JavaConfig またはXMLのBean定義に基づいて、Spring Beanがインスタンス化されます。
インスタンス化はフレームワークが自動で行ってくれて、最終的にJava Beanが「使用可能な状態」になります。
この「使用可能な状態」になったJava BeanをDIコンテナが管理してくれて、プログラマが書いたコードに注入(DI)してくれるわけです。
結論から述べると、以下の図のとおりになります。
このフローに沿ってBeanが「使用可能な状態」になると、DIコンテナがそれらのBeanを管理してくれて、プログラマが書いたコードに注入(DI)してくれます。そして、Beanが不要になると、DIコンテナから削除されます。 Spring Bean Factory は、Spring Containerを介して作成されたBeanのライフサイクルを管理します。
1.1 Beanのライフサイクルにおける独自処理を行いたい場合
Beanのライフサイクル上で、何ら化の独自処理を実行したい場合、用途に応じたコールバックメソッドが用意されているので、それを使用します。
これらのメソッドは、大きく2つのグループに分類できます。
- 初期化後のコールバックメソッド
- 破棄前のコールバックメソッド
以下で、ライフサイクル上で実行できるコールバックメソッドについて詳しく述べます。
2.コールバックメソッド
Springフレームワークは、Beanのライフサイクルイベントを制御するために次の4つの方法を提供しています。
- InitializingBeanおよびDisposableBeanコールバックインターフェイス
- 特定の動作をさせるための *Awareインターフェイス
- 独自に定義可能なinit() およびdestroy() メソッド
- @PostConstructおよび@PreDestroyアノテーション
この4つを順に説明していきます。
2.1 InitializingBeanおよびDisposableBean
org.springframework.beans.factory.InitializingBeanインターフェースを実装したクラスは、Beanのセットアップに必要なすべてのプロパティをコンテナが設定した後に行う初期化処理を定義できます。
InitializingBeanを実装したクラスでは、afterPropertiesSet()メソッドを実装する必要があります。
void afterPropertiesSet() throws Exception;
ちなみに、InitializingBeanを使ってBeanの初期化をすることは非推奨だそうです。
その理由は、BeanクラスとSpringコンテナが密結合になるためです。
ここで言う「密結合」の意味は、BeanクラスがSpringフレームワークを使うことを前提とした作りになってしまうということだと思っています。
つまり、IoC(=Inversion of Control=制御の反転)において、Beanは「誰から使われるBeanなのか?」を気にすることなく設計すべきなのに、InitializingBeanを使うことによって、「SpringフレームワークのDIコンテナから使われるBeanである」ということが前提の作りになってしまいます。
↑の青字部分、あくまでも自分の理解なので、間違っていればご指摘いただけると幸いです。
よりBetterな代替方法は、applicationContext.xmlのBean定義で「init-method」を使用することです。
同様に、org.springframework.beans.factory.DisposableBeanインターフェースを実装すると、コンテナが破棄されるときにBeanがコールバックを取得できます。
void destroy() throws Exception;
2.2 特定の動作をさせるための *Awareインターフェイス
Springは、Beanが特定のインフラストラクチャ依存性を必要とすることをコンテナに示すことを可能にする一連の*Awareインターフェイスを提供します。 各インターフェイスでは、Beanに依存関係を注入するメソッドを実装する必要があります。
Awareインタフェース | Overrideの必要があるメソッド | 目的 |
---|---|---|
ApplicationContextAware | void setApplicationContext (ApplicationContext applicationContext) throws BeansException; | 実行されるApplicationContextの通知を希望するオブジェクトによって実装されるインターフェイス。 |
ApplicationEventPublisherAware | void setApplicationEventPublisher (ApplicationEventPublisher applicationEventPublisher); | このオブジェクトが実行されるApplicationEventPublisherを設定します。 |
BeanClassLoaderAware | void setBeanClassLoader (ClassLoader classLoader); | BeanクラスローダーをBeanインスタンスに提供するコールバック。 |
BeanFactoryAware | void setBeanFactory (BeanFactory beanFactory) throws BeansException; | 所有ファクトリをBeanインスタンスに提供するコールバック。 |
BeanNameAware | void setBeanName(String name); | このBeanを作成したBeanファクトリーでBeanの名前を設定します。 |
BootstrapContextAware | void setBootstrapContext (BootstrapContext bootstrapContext); | このオブジェクトが実行されるBootstrapContextを設定します。 |
LoadTimeWeaverAware | void setLoadTimeWeaver (LoadTimeWeaver loadTimeWeaver); | このオブジェクトを含むApplicationContextのLoadTimeWeaverを設定します。 |
MessageSourceAware | void setMessageSource (MessageSource messageSource); | このオブジェクトが実行されるMessageSourceを設定します。 |
NotificationPublisherAware | void setNotificationPublisher (NotificationPublisher notificationPublisher); | 現在の管理対象リソースインスタンスのNotificationPublisherインスタンスを設定します。 |
PortletConfigAware | void setPortletConfig (PortletConfig portletConfig); | このオブジェクトが実行されるPortletConfigを設定します。 |
PortletContextAware | void setPortletContext (PortletContext portletContext); | このオブジェクトが実行されるPortletContextを設定します。 |
ResourceLoaderAware | void setResourceLoader (ResourceLoader resourceLoader); | このオブジェクトが実行されるResourceLoaderを設定します。 |
ServletConfigAware | void setServletConfig (ServletConfig servletConfig); | このオブジェクトが実行されるServletConfigを設定します。 |
ServletContextAware | void setServletContext (ServletContext servletContext); | このオブジェクトが実行されるServletContextを設定します。 |
2.3 独自に定義可能なinit() およびdestroy() メソッド
init()メソッドおよびdestroy()メソッドは、2つの方法で定義できます。
- Beanローカル定義:単一のBeanに適用可能な定義方法。
- グローバル定義:Beanコンテキストで定義されたすべてのBeanに適用可能な定義方法。
2.3.1 Beanローカル定義
<beans> <bean id="testBean" class="com.yuukiygTestBean" init-method="customInit" destroy-method="customDestroy"></bean> </beans>
2.3.2 グローバル定義
グローバル定義は以下のとおりです。 これらのメソッドは、
<beans default-init-method="customInit" default-destroy-method="customDestroy"> <bean id="demoBean" class="com.yuukiyg.DemoBean"></bean> </beans>
上記のBean定義ファイルに書いたメソッド名に対して、以下のようにJavaプログラムで、そのメソッドを定義する必要がある。
public class DemoBean { public void customInit() { System.out.println("Method customInit() invoked..."); } public void customDestroy() { System.out.println("Method customDestroy() invoked..."); } }
2.4 @PostConstructおよび@PreDestroyアノテーション
Spring 2.5以降では、@PostConstruct や @PreDestroyアノテーションを使用してライフサイクルメソッドを指定することもできます。
@PostConstructアノテーションを付与したメソッドは、デフォルトコンストラクタを使用してBeanが生成された後、そのインスタンスが他のオブジェクト(つまり、そのインスタンスを欲しがっているオブジェクト)に対してDIされる直前に呼び出されます。
@PreDestroyアノテーションを付与したメソッドは、BeanがDIコンテナ内で破棄される直前に呼び出されます。
public class DemoBean { @PostConstruct public void customInit() { System.out.println("Method customInit() invoked..."); } @PreDestroy public void customDestroy() { System.out.println("Method customDestroy() invoked..."); } }
つづく・・・