Yan Container−Setter Injection
Yan Containerにクラスを登録して使う(2006.9.24)
Yan ContainerはConstructor InjectionだけでなくSetter Injectionも使うことができる.
まず,FishクラスはConstructor Injectionと同様である.FishermanクラスにはFishクラスを設定するためのsetFish(Fish)メソッドが必要である.
//Fish.java Constructor Injectionと同じ.
public class Fish{
public void fish(Fisherman fisherman){
System.out.println(this+" was fished by "+fisherman);
}
}
//Fisherman.java コンストラクタの代わりにsetterを用意.
public class Fisherman{
Fish fish;
public void setFish(Fish fish){ //Fishクラスを登録するためのsetterメソッドを追加.
this.fish=fish;
}
public void fish(){
fish.fish(this);
}
}
//Main.java
import java.beans.IntrospectionException;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main{
public static void main(String[] args){
Container yan=new DefaultContainer();
try{
yan.registerComponent(Components.bean(Fish.class)); //a. Fishクラスをコンテナに登録
yan.registerComponent(Components.bean(Fisherman.class)); //b. Fishermanクラスをコンテナに登録
}
catch(IntrospectionException e){
e.printStackTrace();
}
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class); //c. Fishermanクラスのインスタンス生成
fisherman.fish(); //d. 魚を釣る
}
}
Mainクラスは以下の手順で魚を釣っている.
Components.bean(java.lang.Class)
メソッドを使って使用するクラス(ここではFishクラスとFishermanクラス)に該当するComponentクラスを生成する(Main.javaのaとb)registerComponent(Component)
メソッドを使ってYan Containerに登録する(Main.javaのaとb)- Fishermanクラスのインスタンスを生成(Main.javaのc)
- 魚を釣る(Main.javaのc)
このプログラムをコンパイル&実行するとこんな結果になる.魚は釣れたようだ.
Fish@27e353 was fished by Fisherman@bd928a
Fishermanクラスのfish()
メソッド実行時に必要なFishクラスのインスタンスは,Yan Containerが自動的に生成する.そして,Fishクラスに定義したsetFish(Fish)
メソッドを使ってFishermanクラスのインスタンス変数に設定してくれる.
クラスに特定の値を指定(2006.10.8)
釣れた魚の種類を付け加えよう.Constructor Injectionの場合はコンストラクタを定義するが,Setter InjectionなのでFishクラスにsetterとしてsetKind(String)
を追加する.
//Fish.java
public class Fish{
private String kind;
public void setKind(String kind){ //魚の種類のsetterを追加
this.kind=kind;
}
public void fish(Fisherman fisherman){
System.out.println(this+"("+kind+") was fished by "+fisherman); //魚の種類も出力しよう
}
}
//Fisherman.java −変更なし−
public class Fisherman{
private String name;
Fish fish;
public void setFish(Fish fish){
this.fish=fish;
}
public void fish(){
fish.fish(this);
}
}
//Main.java
import java.beans.IntrospectionException;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main{
public static void main(String[] args){
Container yan=new DefaultContainer();
yan.registerValue("タイ"); //a. 魚の種類をYan Containerに登録
try{
yan.registerComponent(Components.bean(Fish.class));
yan.registerComponent(Components.bean(Fisherman.class));
}
catch(IntrospectionException e){
e.printStackTrace();
}
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
このプログラムを動かすとこんな結果になる.タイは釣れたようだ.
Fish@27e353(タイ) was fished by Fisherman@bd928a
注意しないといけないのは,Main.javaのaで使っているContainer.registerValue
メソッドは
- Fishクラスの
setKind(String)
の引数に指定したString型の値
ではなく
- Containerに登録した全クラスが使うString型の値
を設定していると言う点である.
例えば,FishermanクラスでもString型の引数(釣り人の名前)を持っていたとしよう.
//Fisherman.java
public class Fisherman{
private String name;
Fish fish;
public void setName(String name){ //String型の引数(釣り人の名前)を持つsetter
this.name=name;
}
public String getName(){
return this.name;
}
public void setFish(Fish fish){
this.fish=fish;
}
public void fish(){
fish.fish(this);
}
}
Fish.javaで釣上げた人の名前を出力する.
//Fish.java
public class Fish{
private String kind;
public void setKind(String kind){
this.kind=kind;
}
public void fish(Fisherman fisherman){
System.out.println(this+"("+kind+") was fished by "+fisherman+"("+fisherman.getName()+")"); //釣り人の名前を出力
}
}
Main.javaは同じである.コンパイル&実行してみよう.
Fish@27e353(タイ) was fished by Fisherman@bd928a(タイ)
釣り人の名前もタイになってしまう.
setterで設定するプロパティを指定(2006.10.22)
魚には魚の名前を,釣り人には釣り人の名前を付けよう.Main.javaを修正する.Fish.javaとFisherman.javaは修正不要である.
import java.beans.IntrospectionException;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main{
public static void main(String[] args){
Container yan=new DefaultContainer();
try{
yan.registerComponent(Components.bean(Fish.class)
.withProperty("kind",Components.value("タイ")));
//a. 第1引数は設定するプロパティの名前.大文字と小文字の区別あり
yan.registerComponent(Components.bean(Fisherman.class)
.withProperty("name",Components.value("浜ちゃん")));
}
catch(IntrospectionException e){
e.printStackTrace();
}
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
Component.withPropertyメソッド(Main.javaのa)を使って,プロパティに値を設定する.withPropertyメソッドの第1引数は設定するプロパティの名前,第2引数は設定する値である.設定する値はComponent型である必要があるので,Components.valueメソッドを使って文字列をComponent型に変換している.
手順を逐一書くならこのようになる.
import java.beans.IntrospectionException;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main{
public static void main(String[] args){
Container yan=new DefaultContainer();
try{
Component fish=Components.bean(Fish.class);
fish=fish.withProperty("kind",Components.value("タイ"));
yan.registerComponent(fish);
Component fisherman=Components.bean(Fisherman.class);
fisherman=fisherman.withProperty("name",Components.value("浜ちゃん"));
yan.registerComponent(fisherman);
}
catch(IntrospectionException e){
e.printStackTrace();
}
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
コンテナから取り出す(Container.getInstanceOfTypeメソッドを使う)のはFishermanオブジェクトだけなので,Fish.classは登録しなくても良い.
import java.beans.IntrospectionException;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main2{
public static void main(String[] args){
Container yan=new DefaultContainer();
try{
Component fish=Components.bean(Fish.class).withProperty("kind",Components.value("タイ"));
//Fish.classはコンテナには登録しない.Componentオブジェクトを作成するだけ.
yan.registerComponent(Components.bean(Fisherman.class)
.withProperty("name",Components.value("浜ちゃん"))
.withProperty("fish",fish));
//withPropertyメソッド経由でsetFishメソッドを使い,Fishermanオブジェクトのfishプロパティに値を設定.
}
catch(IntrospectionException e){
e.printStackTrace();
}
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
コンストラクタとbean(2006.11.5)
JavaBeanでは,使用できるコンストラクタはパラメータのないコンストラクタのみである.しかし,Yan Containerでは,パラメータのあるコンストラクタをもつbeanを使うこともできる.
まず,FishクラスとFishermanクラスにコンストラクタを定義しよう.
//Fish.java
public class Fish{
private String kind;
public Fish(){ //デフォルトコンストラクタを追加
}
public Fish(String kind){ //パラメータのあるコンストラクタを追加
this.setKind(kind);
}
public void setKind(String kind){
this.kind=kind;
}
public void fish(Fisherman fisherman){
System.out.println(this+"("+kind+") was fished by "+fisherman+"("+fisherman.getName()+")");
}
}
//Fisherman.java
public class Fisherman{
private String name;
Fish fish;
public Fisherman(){ //デフォルトコンストラクタを追加
}
public Fisherman(String name,Fish fish){ //パラメータのあるコンストラクタを追加
this.setName(name);
this.setFish(fish);
}
public void setName(String name){
this.name=name;
}
public String getName(){
return this.name;
}
public void setFish(Fish fish){
this.fish=fish;
}
public void fish(){
fish.fish(this);
}
}
[setterで設定するプロパティを指定]で使用したMain.javaをそのまま使ってみよう.
//Main.java
import java.beans.IntrospectionException;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main{
public static void main(String[] args){
Container yan=new DefaultContainer();
try{
Component fish=Components.bean(Fish.class).withProperty("kind",Components.value("タイ"));
yan.registerComponent(Components.bean(Fisherman.class)
.withProperty("name",Components.value("浜ちゃん"))
.withProperty("fish",fish));
}
catch(IntrospectionException e){
e.printStackTrace();
}
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
これを実行するとこんな結果になる.
Fish@153f67e(タイ) was fished by Fisherman@15bdc50(浜ちゃん)
FishクラスとFishermanクラスをbeanとして扱うためにはデフォルトコンストラクタ(引数のないコンストラクタ)が必須である.これがなかった場合,以下のようにIllegalArgumentExceptionが発生する.
java.lang.IllegalArgumentException: constructor not found for: Fish()
at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:180)
at org.apache.tools.ant.taskdefs.Java.run(Java.java:710)
at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:178)
at org.apache.tools.ant.taskdefs.Java.execute(Java.java:84)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:275)
at org.apache.tools.ant.Task.perform(Task.java:364)
コンストラクタインジェクションでも使うことができる.Fish.javaとFisherman.javaには変更はない.
//Main2.java
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main2{
public static void main(String[] args){
Container yan=new DefaultContainer();
Component fish=Components.ctor(Fish.class,new Class[]{String.class})
.withArgument(0,Components.value("タイ"));
yan.registerComponent(Components.ctor(Fisherman.class,new Class[]{String.class,Fish.class})
.withArgument(0,Components.value("浜ちゃん"))
.withArgument(1,fish));
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
実行するとこんな結果になる.
Fish@fe748f(タイ) was fished by Fisherman@1968e23(浜ちゃん)
コンストラクタインジェクションで作成したComponentに,beanとしてプロパティを設定することもできる.
import java.beans.IntrospectionException;
import jfun.yan.Component;
import jfun.yan.Components;
import jfun.yan.Container;
import jfun.yan.containers.DefaultContainer;
public class Main3{
public static void main(String[] args){
Container yan=new DefaultContainer();
Component fish=Components.ctor(Fish.class,new Class[]{String.class})
.withArgument(0,Components.value("タイ"));
Component fisher=Components.ctor(Fisherman.class,new Class[]{String.class,Fish.class})
.withArgument(0,Components.value("浜ちゃん"))
.withArgument(1,fish); //コンストラクタインジェクションでComponentを作成
try{
fisher=Components.bean(fisher)
.withProperty("name",Components.value("スーさん"))
.withProperty("fish",fish); //beanとしてプロパティを設定.
}
catch(IntrospectionException e){
e.printStackTrace();
}
yan.registerComponent(fisher);
Fisherman fisherman=(Fisherman)yan.getInstanceOfType(Fisherman.class);
fisherman.fish();
}
}
実行するとこうなる.当然といえば当然だが,後から設定したプロパティが有効である.
[java] Fish@19836ed(タイ) was fished by Fisherman@3e0ebb(スーさん)