DIVE INTO S2 .HACK : INCLUDE PART II+
Seasar2に慣れ親しむためにS2Containerをプチハックしてみる第2.5弾。 (^^;;;
- カスタムPathResolverを使って、S2Container間の依存関係(include)をDEPENDENCY-LOOKUPからDEPENDENCY-INJECTIONにしてみる。
- てゆうか、既存のdiconファイルの設定を変更することなく、一部のdiconファイルを差し替える。 (^^;;;
ResourceResolverを使用してやってみる予定だったのですが、PathResolverをいじらずに、前回とおなじようなことをするためには、XmlS2ContainerBuilderにも変更を加える必要があったので、前のPathResolver版に蛇の足を付けてお茶を濁す…
今回は、既存のdiconファイルを、さらに上位のdiconファイルでインクルードすることで、diconツリーの一部のdiconを差し替えてみたり…なんか、視点が、DEPENDENCY-LOOKUPとかINJECTIONとかじゃなくなってきたような…orz
-
- 想定する既存のdiconファイル群は、こんな感じです。*1
- ごく普通のdiconファイルたち。
■org/seasar/framework/container/factory/PathAliasResolverTest2.Node0a.dicon
component0
component1
component2
"Here is node0a container."
■org/seasar/framework/container/factory/PathAliasResolverTest2.Node1a.dicon
"Here is node1a container."
■org/seasar/framework/container/factory/PathAliasResolverTest2.Node2a.dicon
"Here is node2a container."
■org/seasar/framework/container/factory/PathAliasResolverTest2.Node2b.dicon
"Here is node2b container."
-
- で、これらの上位に位置させて、既存のdiconを差し替えるためのルートdiconファイルがこちら。
- 1目のincludeで、Node2aをNode2bに差し替えている。
■org/seasar/framework/container/factory/PathAliasResolverTest2.dicon
<include path="org/seasar/framework/container/factory/PathAliasResolverTest2.Node2a.dicon
=org/seasar/framework/container/factory/PathAliasResolverTest2.Node2b.dicon"/>
-
- テストコードは、こんな感じで。
■org/seasar/framework/container/factory/PathAliasResolverTest2.java
package org.seasar.framework.container.factory;import java.util.List;
import junit.framework.TestCase;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.util.ClassUtil;/**
* @author hidebsd
*/
public class PathAliasResolverTest2 extends TestCase {private static final String BASE = ClassUtil.getResourcePath(PathAliasResolverTest2.class).replaceAll("\\.class$", "");
private static final String S2CFG = BASE + ".Configuration.dicon";private static final String PATH0 = BASE + ".Node0a.dicon";
private static final String PATH1 = BASE + ".dicon";
public void setUp() {
S2ContainerFactory.configure(S2CFG);
}public void testDefaultSettings() throws Exception {
S2Container container = S2ContainerFactory.create(PATH0);
container.init();
List list = (List) container.getComponent("collection");
for (int i = 0; i < list.size(); ++i) {
assertEquals("node" + i, "Here is node" + i + "a container.", list.get(i));
}
}public void testOverrideSettings() throws Exception {
S2Container container = S2ContainerFactory.create(PATH1);
container.init();
List list = (List) container.getComponent("collection");
for (int i = 0; i < list.size(); ++i) {
String node = "node" + i + (i != 2 ? "a" : "b");
assertEquals("node" + i, "Here is " + node + " container.", list.get(i));
}
}
}
-
- で、S2コンテナカスタマイズ用diconはこんな感じで。PathResolverインターフェースを実装しているクラスがあると差し替えられるので、これでOK。
- ちなみに、s2container.dicon というファイル名でクラスパスのルートに置けば、明示的に S2ContainerFactory.configure(…) しなくても、自動的にそのファイルを読み込んで、S2コンテナがカスタマイズされます。
■org/seasar/framework/container/factory/PathAliasResolverTest2.Configuration.dicon
■org/seasar/framework/container/factory/PathAliasResolver.java
package org.seasar.framework.container.factory;import java.util.HashMap;
import java.util.Map;import org.seasar.framework.util.ClassUtil;
import org.seasar.framework.util.StringUtil;/**
* @author hidebsd
*/
public class PathAliasResolver implements PathResolver {private static final String TRIM = "[\\n\\r\\t ]*";
private static final String dummyConfigPath = ClassUtil.getResourcePath(
PathAliasResolver.class).replaceAll("\\.class$", "Dummy.dicon");private final Map aliasDefinitions = new HashMap();
private String delimiter = "=";
public PathAliasResolver() {
}public PathAliasResolver(String delimiter) {
this.delimiter = delimiter;
}public void setDelimiter(String delimiter) {
this.delimiter = delimiter;
}public String resolvePath(String context, String path) {
if (path == null) {
throw new IllegalStateException("Specified path was null.");
}
path = trimPath(path);
if (path.contains(delimiter)) {
path = registerPathAlias(path);
}
if (aliasDefinitions.containsKey(path)) {
path = resolvePath(path);
}
return path;
}private String trimPath(String path) {
path = path.replaceAll("^" + TRIM, "");
path = path.replaceAll(TRIM + "$", "");
path = path.replaceAll(TRIM + delimiter + TRIM, delimiter);
return path;
}private String registerPathAlias(String path) {
int pos = path.indexOf(delimiter);
String alias = path.substring(0, pos);
if (!aliasDefinitions.containsKey(alias)) {
path = path.substring(pos + delimiter.length());
path = (path.length() != 0 ? path : dummyConfigPath);
aliasDefinitions.put(alias, path);
}
return dummyConfigPath;
}private String resolvePath(String path) {
String resolvedPath = (String) aliasDefinitions.get(path);
if (resolvedPath == null) {
return path;
}
return resolvedPath;
}}
-
- それから、diconファイルパスの別名を登録する場合、返すパスがないのですが、なにかしらdiconファイルのパスを返す必要があったので、ダミーのdiconファイルを作成。
- これは、なんとかならないかなぁ…。やっぱりIncludeTagHandlerで対処するしかないかなぁ…、ま、実行に影響はないからいっか…。
■org/seasar/framework/container/factory/PathAliasResolverDummy.dicon
-
- では、テスト開始〜!
- RED RED RED RED RED RED GREEN!
- Y-A-T-T-A-A !!!
- さらなる深みを目指して、DIVE INTO S2 !