Spring+HibernateEntityManager(コンポーネント自動検出 with アノテーション編)

SpringFramework2.5から、クラスパスを走査し、アノテーションの付加されたコンポーネントを自動検出する機能がサポートされています。典型的には、@Component, @Repository, @Service, @Controller 等のステレオタイプでアノテートされたコンポーネントクラスが対象になります。


マニュアルの該当項目

自動検出を行わず、手動で設定する場合

以前は、以下のように Entity を bean として登録していましたが、今回はこれを自動検出してみようと思います。

<bean id="user" class="domain.entity.UserImpl" scope="prototype" />

context:component-scan 要素

コンポーネントの自動検出を行うためには、context:component-scan 要素を使用します。


上記のエンティを自動検出するために、beans.xml に以下のような設定を行います。

<context:component-scan base-package="domain.entity" />


上記の設定と、以降で説明するアノテーションにより user bean は自動検出されるようになるため、下記の設定は beans.xml から必要なくなります。

<bean id="user" class="domain.entity.UserImpl" scope="prototype" />

アノテーションによる bean の自動検出と設定

user bean を設定するために、以下の2つの定義をアノテーションで行います。

  • domain.entity.UserImpl クラスを、"user" という名前の beanとして登録する。
  • bean のスコープを、prototype にする。
@Component アノテーション

UserImplクラスに、@Component アノテーションを追加します。

@Component

この状態だと、bean 名が userImpl になってしまうため、アノテーションvalue に文字列 "user" を渡します。

@Component("user")

正直言うと、value まで指定すると、アプリケーション層の概念がドメイン層に混入するような気がするので、ちょっと気が進みません。しかし、Entity に限っては、おいらの経験上、このような命名規則で困ることはほぼないと思うので、value を指定してしまいます。(と言いつつ、このアノテーションごと必要なくなる手を打つ予定ですがw)

@Scope アノテーション

@Scope アノテーションにより、bean のスコープを定義できます。

以下のように指定し、prototype スコープに設定します。

@Scope("prototype")

ソース

UserImpl.java
package domain.entity;

import infrastracture.DomainEntityBaseWithSurrogateIntegerKey;

import javax.persistence.Entity;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * {@link User} の実装クラスです。
 * 
 * @author beyondseeker
 * @version $Id$
 */
@Entity(name = "User")
@Component("user")
@Scope("prototype")
public class UserImpl extends DomainEntityBaseWithSurrogateIntegerKey implements User<Integer> {
    
    /**
     * ユーザー名
     */
    private String name;
    
    /**
     * {@inheritDoc}
     */
    @Override
    public Class<?> getDomainEntityInterface() {
        return User.class;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public String getName() {
        return name;
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void setName(String name) {
        this.name = name;
    }
    
}

下記の2つのアノテーションが追加されています。

@Component("user")
@Scope("prototype")
beans.xml

削除

<!-- Entity -->
<bean id="user" class="domain.entity.UserImpl" scope="prototype" />


追加

<!-- Entity Bean Registration -->
<context:component-scan base-package="domain.entity" />

結果

ソースにアノテーションは増えましたが、各 Entity を定義するソースは1箇所となり、保守性が向上しました。(とおいらは思う)


次回はさらにシェイプアップ!(の予定)