Search on the blog

2013年2月11日月曜日

Learn Spring Framework (2)

アノテーションを使ったBeanの定義およびBeanのインジェクションについて復習しました。

アノテーションによるBean定義
まずBeanの定義についておさらいです。
  • @Component
  • @Service
  • @Repository
  • @Controller
のいずれかをクラスに付与することで、BeanをSpring配下で管理することができるようになります。どのアノテーションを使ってもBeanを登録するという意味では同じですが、後で管理しやすいように(AOPのポイントカットのtargetにアノテーション使うとか)使い分けるのがいいと思います。
一般的には、サービス層のクラスには@Serivice、データ層のクラスには@Repository、コントローラー層のクラスには@Contoroller、どれにも当てはまらない場合は@Componentを付けます。

アノテーションによるBeanのインジェクション
アノテーションによるBeanの注入には、@Autowiredまたは@Resourceが利用できます。@Autowiredは型情報による注入、@ResourceはBeanの名前による注入を行います。

サンプル
サービス層のクラスにDaoのBeanを注入する例です。
Bean定義ファイルのcomponent-scanのbase-packageを書き換えることで、implクラス、stubクラスを切り替えることができます。この例だとあまりありがたさが伝わりませんが、Daoが何個もあってすべてのDaoのimpl/stubを一発で切り替えることができると考えるととても便利ですねー。

まずBean定義ファイル。Beanの定義はアノテーションを利用するので、ここには一つ一つのBeanの定義を書く必要はありません。component-scanタグで「ここからアノテーションのついているBeanを探して自動で登録してね。」という指定をするだけでOKです。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
               
     <context:component-scan base-package="main.java.service"/>
     <context:component-scan base-package="test.java.dao"/>
     
</beans>
次に、サービス層のクラス定義。@ServiceでBean定義しているところと、@Autowiredで型情報を元にDaoが注入されるようにしているところがポイント。アノテーションによるインジェクションの設定が行えるようになったことで、setter injectionとかconstructor injectionとかを行うためのメソッドが不要になりました。
package main.java.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import main.java.util.BeanFactory;
import main.java.dao.SomeDao;

@Service("SomeService")
public class SomeService {
    @Autowired
    private SomeDao dao;
    
    public void doService() {
        dao.create();
        dao.read();
        dao.update();
        dao.delete();
    }
    
    public static void main(String[] args) {
        SomeService service = (SomeService)BeanFactory.getBean("SomeService");
        service.doService();
    }
}
Daoのインターフェース。サービスクラスのソースコードで使われているのは実装クラスではなくこのインターフェースのみってところがポイントです。
package main.java.dao;

public interface SomeDao {
    public void create();
    public void read();
    public void update();
    public void delete();
}
Daoの実装クラス。Implとしておきました。ここではそうなっていませんが、実際にDBアクセスを行う部分だと思ってください。
package main.java.dao;

import org.springframework.stereotype.Repository;

@Repository("SomeDao")
public class SomeDaoImpl implements SomeDao {

    @Override
    public void create() {
        System.out.println("SomeDaoImpl#create()");
    }

    @Override
    public void read() {
        System.out.println("SomeDaoImpl#read()");
    }

    @Override
    public void update() {
        System.out.println("SomeDaoImpl#update()");
    }

    @Override
    public void delete() {
        System.out.println("SomeDaoImpl#delete()");
    }

}
Daoの実装クラス。スタブです。サービスが利用するSomeDaoの実装クラスはcomponent-scanする場所を変えることで切り替えることができるというのがポイントです。クライアントクラスであるサービスクラスを書き換える必要はありません。
package test.java.dao;

import main.java.dao.SomeDao;

import org.springframework.stereotype.Repository;

@Repository("SomeDao")
public class SomeDaoStub implements SomeDao {

    @Override
    public void create() {
        System.out.println("SomeDaoStub#create()");
    }

    @Override
    public void read() {
        System.out.println("SomeDaoStub#read()");
    }

    @Override
    public void update() {
        System.out.println("SomeDaoStub#update()");
    }

    @Override
    public void delete() {
        System.out.println("SomeDaoStub#delete()");
    }

}

0 件のコメント:

コメントを投稿