Spring+HibernateEntityManager(@Resource編)

今回は、前回の続きです。

@Resource アノテーションとは?

@Resource アノテーションは、クラス、メソッド、フィールドに対して指定可能なアノテーションで、リソースへの参照を宣言するためのものです。JSR 250: Common Annotations for the JavaTM Platform で定義されてるため、特定のフレームワークに依存しません。説明は、Common Annotations for the JavaTM PlatformTM Final Release の 2.3 javax.annotation.Resource に書かれています。ページ数は5ページ程度なので、ちょっと空いた時間を利用して読むのもアリかと。

SpringFramework 上での @Resource アノテーション

JSR-250 による定義では、@Resource の name 要素はリソースの JNDI 名です。しかし、SpringFramework のデフォルトの動作としては、bean 名を対象とします。未指定の場合は、フィールド名やメソッド名から導き出された名前を使用します。

前回のサンプル

これから @Resource アノテーションを、前回作成したサンプルに適用していきます。


まずは、前回作成したサンプルから、EntityManager に関する部分を抜粋したものを示します。

ServiceBase.java
/**
 * EntityManager
 */
private EntityManager entityManager;

/**
 * EntityManager をセットします。
 * 
 * @param entityManager
 *            EntityManager
 */
@Required
public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

/**
 * EntityManager を返します。
 * 
 * @return EntityManager
 */
public EntityManager getEntityManager() {
    return entityManager;
}
beans.xml
<bean id="userService" class="domain.service.UserServiceImpl">
  <lookup-method name="newUser" bean="user"/>
  <property name="entityManager" ref="entityManager"/>
</bean>

変更前にリファクタしましょう。

@Resource アノテーションを適用する前に、現行ソースをリファクタします。サブクラスで、いちいち getEntityManager() とかやるのはめんどいので、フィールドを protected にして、getter メソッドを削除します。

ServiceBase.java(リファクタ後)
/**
 * EntityManager
 */
protected EntityManager entityManager;

/**
 * EntityManager をセットします。
 * 
 * @param entityManager
 *            EntityManager
 */
@Required
public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

ちょっとだけシンプルになりました。(`・ω・´)

変更前のソースのポイント

変更前のソースには、以下のようなポイントがあります。

UserServiceImpl.java
  • 【長所】entityManager に値がセットされることを、@Required アノテーションにより保証する。
  • 【短所】@Required アノテーションは、org.springframework.beans.factory.annotation パッケージに所属しているため、Spring Framework に依存している。
beans.xml
  • 【長所】userService bean の定義で、entityManager をインジェクションしている。
  • 【長所】アプリケーション構成を beans.xml から見渡せる。

@Resource アノテーションを SpringFramework 上で使ってみる

それでは、現行のソースを、@Resource アノテーションを利用したソースに変更してみたいと思います。

UserServiceImpl.java
/**
 * EntityManager
 */
@Resource
protected EntityManager entityManager;

setter メソッドをさっくりと削除しました。


以下のように1行で書いてもよさそうですね〜。

@Resource protected EntityManager entityManager;
beans.xml
<bean id="userService" class="domain.service.UserServiceImpl">
  <lookup-method name="newUser" bean="user"/>
</bean>

entityManager の DI 用途の1行が削除されました。


ソースがずいぶんシンプルになった ヽ( ・∀・)ノ ワーイ

@Resource アノテーションの効果

@Resource アノテーションを適用した際に注目すべき点考えてみます。

  • ServiceBase.java
    • 【メリット】setter が無くなり、ソースがシンプルになった。
    • 【メリット】@Required アノテーションが無くなり、SpringFramework への依存が無くなった。
    • 【ポイント】@Required アノテーションがなくなったが、@Resource アノテーションにより、以前と同様に、値がセットされることが保証される。
  • beans.xml
    • 【メリット】ServiceBase.java 上の @Resource アノテーションにより、entityManager の setter injection 用のプロパティ設定をしなくて済むようになった。
    • 【要検討】アプリケーション構成を、beans.xml だけからでは見渡せなくなった。@Resoruce アノテーションが、値がセットされることを保証しているため、値がセットされないことが原因で、実行時に NullPointerException という状態は避けれるので、まぁ、ありかな。

使いすぎは禁物?

ソースはシンプルになるかもしれませんが、Layered Architecture を破壊する可能性を秘めているような、、、。

今はちょっと思いつきませんが、DIの定義の都合で、ドメイン層のソースを書き換えるような事態が発生するような危険性ってないのかな?

思いついたら追記します o...rz