Seasar2.3その3

id:koichik:20051014#1129312812


自分の間違いについて訂正していただきました。ありがとうございます。
いかん、何回も間違えっぱなしだ・・・こういう解決策があるなら、メーリングリストに投稿しておけばよかったですね。
さて、間違いや問題点はちゃんと明らかにしておかなければいけないので、早速実験。
まずは、id:da-yoshi:20051013#1129148115で作ったサンプルの、テスト用クラスをちょっと変更。

package test;

public interface Test {

	String getMessage();

}
package test.client;

public interface TestClient {

	void execute();
}
package test.impl;

import test.Test;
import test.annotation.Trace;
import test.annotation.Transaction;

public class TestImpl implements Test {

	@Transaction
	public String getMessage() {
		return getMessage2();
	}

	@Trace
	public String getMessage2() {
		return "こんにちは";
	}

}
package test.impl2;

import test.Test;
import test.annotation.Transaction;

public class Test2Impl implements Test {

	@Transaction
	public String getMessage() {
		return "Hello";
	}

}
package test.client.impl;

import test.Test;
import test.client.TestClient;

@Component(name = "impl1")
public class TestClientImpl implements TestClient {
	
	private Test test;

	public void setTest(Test test) {
		this.test = test;
	}

	public void execute() {
		System.out.println("TestClientImpl:" + test.getMessage());

	}

}
package test.client.impl2;

import test.Test;
import test.annotation.Trace;
import test.client.TestClient;

@Component(name = "impl2")
public class TestClient2Impl implements TestClient {

	private Test test;

	public void setTest(Test test) {
		this.test = test;
	}
	
	@Trace
	public void execute() {
		System.out.println("TestClient2Impl:" + test.getMessage());

	}

}

TestインターフェイスとTestClientインターフェイスを、2人の開発者が別のパッケージでそれぞれ実装した・・・という前提です。TestClient実装クラスを今回mainメソッドで呼び出す為、この2つの実装クラスだけはCompomentアノテーションでname定義を行いました。
この2つをそれぞれ実行すると・・・

EDEBUG 2005-10-15 09:05:13,906 [main] トランザクションを開始しました
DEBUG 2005-10-15 09:05:13,906 [main] BEGIN test.impl.TestImpl#getMessage2()
DEBUG 2005-10-15 09:05:13,906 [main] END test.impl.TestImpl#getMessage2() : こんにちは
DEBUG 2005-10-15 09:05:13,906 [main] トランザクションをコミットしました
TestClientImpl:こんにちは
DEBUG 2005-10-15 09:05:55,562 [main] BEGIN test.client.impl2.TestClient2Impl#execute()
DEBUG 2005-10-15 09:05:55,578 [main] トランザクションを開始しました
DEBUG 2005-10-15 09:05:55,578 [main] BEGIN test.impl.TestImpl#getMessage2()
DEBUG 2005-10-15 09:05:55,578 [main] END test.impl.TestImpl#getMessage2() : こんにちは
DEBUG 2005-10-15 09:05:55,578 [main] トランザクションをコミットしました
TestClient2Impl:こんにちは
DEBUG 2005-10-15 09:05:55,578 [main] END test.client.impl2.TestClient2Impl#execute() : null

Clientはそれぞれ呼び出されたのですが、そこにセットされてるTestインターフェイスの実装を使い分けることが出来ません。Testの実装クラスについてもComponentアノテーションで名前をつけてやって、Binding定義を追加すれば上手くいくんでしょうけど・・・それじゃS2の自動バインディング定義の恩恵が受けられない。Testクラスが共通的なクラスだったら、いちいち設定せずに使いたいですし。
そこで早速、教えていただいた「AutoRegisterを分割したdiconファイルに定義する」方法を使ってみたいと思います。

aop2.diocn

自作のアスペクト関連クラスをここに定義

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC
    "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">

<components>
	<include path="aop.dicon"/>
	<include path="j2ee.dicon"/>

    <component name="annotationTraceInterceptor"
    	class="test.interceptor.AnnotationMethodInterceptor">
    	<property name="interceptor">aop.traceInterceptor</property>
    	<property name="annotationClass">@test.annotation.Trace@class</property>
    </component>
    
    <component name="annotationTransactionInterceptor"
    	class="test.interceptor.AnnotationMethodInterceptor">
    	<property name="interceptor">j2ee.requiredTx</property>
    	<property name="annotationClass">@test.annotation.Transaction@class</property>
    </component>
    
</components>
impl1.dicon

開発者1用dicon

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC
    "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">

<components namespace="test1">
	<include path="aop2.dicon"/>

	<component
  		class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    	<property name="autoNaming">
    		<component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    	</property>
    	<initMethod name="addClassPattern">
    		<arg>"test.impl"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
    	<initMethod name="addClassPattern">
    		<arg>"test.client.impl"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
    	<initMethod name="registAll"/>
    </component>
    
    <component
      class="test.interceptor.AnnotationAspectAutoRegister">
        <property name="interceptorMap">
        	#{@test.annotation.Trace@class : "annotationTraceInterceptor",
        	@test.annotation.Transaction@class : "annotationTransactionInterceptor"}
        </property>
    	<initMethod name="addClassPattern">
    		<arg>"test.impl"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
    	<initMethod name="addClassPattern">
    		<arg>"test.client.impl"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
        <initMethod name="registAll"/>
    </component>
    
</components>
impl2.dicon

開発者2用dicon

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC
    "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">

<components namespace="test2">
	<include path="aop2.dicon"/>

	<component
  		class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    	<property name="autoNaming">
    		<component class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    	</property>
    	<initMethod name="addClassPattern">
    		<arg>"test.impl2"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
    	<initMethod name="addClassPattern">
    		<arg>"test.client.impl2"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
    	<initMethod name="registAll"/>
    </component>
    
    <component
      class="test.interceptor.AnnotationAspectAutoRegister">
        <property name="interceptorMap">
        	#{@test.annotation.Trace@class : "annotationTraceInterceptor",
        	@test.annotation.Transaction@class : "annotationTransactionInterceptor"}
        </property>
    	<initMethod name="addClassPattern">
    		<arg>"test.impl2"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
    	<initMethod name="addClassPattern">
    		<arg>"test.client.impl2"</arg>
    		<arg>".*Impl"</arg>
    	</initMethod>
        <initMethod name="registAll"/>
    </component>
</components>
app.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC
    "-//SEASAR//DTD S2Container 2.3//EN"
    "http://www.seasar.org/dtd/components23.dtd">

<components>
	<include path="impl1.dicon"/>
	<include path="impl2.dicon"/>
    
</components>

では、まずは、test1.impl1のexecuteメソッドを呼び出し

DEBUG 2005-10-15 09:16:45,406 [main] トランザクションを開始しました
DEBUG 2005-10-15 09:16:45,421 [main] BEGIN test.impl.TestImpl#getMessage2()
DEBUG 2005-10-15 09:16:45,421 [main] END test.impl.TestImpl#getMessage2() : こんにちは
DEBUG 2005-10-15 09:16:45,421 [main] トランザクションをコミットしました
TestClientImpl:こんにちは

次に、test2.impl2を呼び出し

DEBUG 2005-10-15 09:17:27,281 [main] BEGIN test.client.impl2.TestClient2Impl#execute()
DEBUG 2005-10-15 09:17:27,312 [main] トランザクションを開始しました
DEBUG 2005-10-15 09:17:27,312 [main] トランザクションをコミットしました
TestClient2Impl:Hello
DEBUG 2005-10-15 09:17:27,312 [main] END test.client.impl2.TestClient2Impl#execute() : null

ファイルで分割するのと同じように、重複したインターフェイスの実装クラスを使い分け、ネームスペースを使うことも出来ました。成功です!
impl1.dicon、impl2.diconはパッケージの定義以外は全部同じに書けますから、業務毎に基盤担当が予めdiconファイルを用意しておけば、各開発担当はdiconファイルをまったく触らずに開発する・・・みたいな運用も出来そうですね。おぉ、これなら今すぐにでも導入したい(笑)
ちょっと気になったのですが、実はmainメソッドから「impl1」「impl2」と実行しただけで呼び出せてしまいました。ネームスペースの定義が無くても呼び出せるんだったっけ・・・ここら辺はもう一度Container関連を勉強し直す必要があるのかも?