Search on the blog

2012年8月28日火曜日

Spring Framework -オブジェクトの生成-

Spring Frameworkについて、基本的な機能を簡単に紹介します。
  1. オブジェクトの生成
  2. Dependency Injection
  3. Aspect Oriented Programming
の3つの機能を3回のpostに分けて書きます。まずは、オブジェクトの生成から書きます。

XML設定ファイルを利用したオブジェクトの生成
// src/cc/co/goodpreparations/Main.java 

package cc.co.goodpreparations;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        
        Person person =  (Person)context.getBean("person");

        person.saySomething();
    }
}
// src/cc/co/goodpreparations/Person.java

package cc.co.goodpreparations;

public class Person {
    private String message;

       public void setMessage(String message){
          this.message  = message;
       }

       public void saySomething(){
          System.out.println(message);
       }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- src/Beans.xml -->

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="person" class="cc.co.goodpreparations.Person">
       <property name="message" value="Hello!"/>
   </bean>
</beans>
XMLファイルにBeanのidとクラスのマッピングを記述します。使用者はidを指定して対応するクラスのオブジェクトを生成します。普通にnewすればいいんじゃない?と思う人もいるかもしれませんが、上記のようにSpringが提供するコンテナからオブジェクトを生成することで、DI/AOPといった機能が使えるようになります。

フィールド値の設定
オブジェクトを生成するときにフィールドの初期値を設定出来ます。同一のクラスから生成されているがフィールド初期値が異なるインスタンスは、異なるBean idをつけることで区別できます。XMLのproperty要素内でフィールドの設定をしていますが、ここで設定するフィールドには必ずsetter(この例の場合はPerson#setMessage)を定義しなければいけません。(JavaBeansなので当然ですが。)
// src/cc/co/goodpreparations/Main.java
package cc.co.goodpreparations;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        
        Person taro =  (Person)context.getBean("taro");
        taro.saySomething();
        
        Person hanako =  (Person)context.getBean("hanako");
        hanako.saySomething();
        
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- src/Beans.xml -->

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="taro" class="cc.co.goodpreparations.Person">
       <property name="message" value="ぼく太郎!"/>
   </bean>
   <bean id="hanako" class="cc.co.goodpreparations.Person">
       <property name="message" value="わたし花子!"/>
   </bean>
</beans>
と、このように太郎くんと花子さんを作れます。

Beanのスコープ
Beanを生成するときに、そのスコープを設定することができます。
  1. singleton
  2. prototype
  3. request
  4. session
  5. global-session
3.-5.はWebアプリケーションに特化したものなので、ここでは1.と2.のみを説明します。まずはsingleton
// src/cc/co/goodpreparations/Main.java
package cc.co.goodpreparations;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        
        Person person = (Person)context.getBean("person");
        person.setMessage("Goodbye!");
        person.saySomething();
        
        Person person2 = (Person)context.getBean("person");
        person2.saySomething();
        
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- src/Beans.xml -->

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="person" class="cc.co.goodpreparations.Person" scope="singleton">
       <property name="message" value="Hello!"/>
   </bean>
</beans>
scope="singleton"のところに注目です。名前から想像がつくように、scopeをsingletonにすると同一のidを持つBeanはアプリケーション上で一つしか作られません。つまり、context#getBeanは毎回同じインスタンスの参照を返します。実行結果は
>Goodbye!
>Goodbye!
となります。ちなみにデフォルトのスコープはsingletonです。scope属性を明記しなかった場合、そのBeanのスコープはsingletonになります。
次に、prototypeを試してみます。先ほどと同様の例でscope属性のみをprototypeに変更すると、実行結果は
>Goodbye!
>Hello!
になります。スコープをprototypeにすると、毎回異なるインスタンスが生成されます。

コールバック関数の指定
Beanが生成されたとき/破棄されるときに、何か処理をしたい場合はコールバック関数を指定することができます。
// src/cc/co/goodpreparations/Main.java
package cc.co.goodpreparations;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
        
        Person person = (Person)context.getBean("person");
        person.saySomething();
        person = null;
         ((AbstractApplicationContext) context).registerShutdownHook();
    }
}
// src/cc/co/goodpreparations/Person.java
package cc.co.goodpreparations;

public class Person {
    private String message;

       public void setMessage(String message){
          this.message  = message;
       }

       public void saySomething(){
          System.out.println(message);
       }
       
       public void initFunc() {
           System.out.println("A Person Bean is created!");
       }

       public void destroyFunc() {
           System.out.println("A Person Bean is destroyed!");
       }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- src/Beans.xml -->

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="person" class="cc.co.goodpreparations.Person" scope="singleton"
            init-method="initFunc" destroy-method="destroyFunc">
       <property name="message" value="Hello!"/>
   </bean>
</beans>
XMLファイルのbean要素のinit-method属性、destroy-method属性にて、コールバックしたい関数を指定することができます。これは便利です。mainメソッド内でAbstractApplicationContext#registerShutdownHookを呼んでいますが、これを呼ぶことで確実にBeanが破棄されdestroy-methodで指定した関数が呼ばれるようにしています。


0 件のコメント:

コメントを投稿