|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 作者 | 正文 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
最后更新时间:2008-04-25
在日本,Seasar2这个框架十分的流行。Seasar2其实就是类似于Spring的一个开源框架 所谓“Seasar2”就是一个“轻量级容器”,面向无法摆脱“Java 应用开发”之烦恼的所谓“开发者”,它能够保证开发的“高生产率和高品质”。并且同“其它轻量级容器”不同的是,“完全不需要书写设定文件”,“就算是应用程序发生改动也无需再次起动即可直接识别变更,因此具有脚本语言的灵活性”。 为了不用写设定文件也能够运行,Convention over Configuration的思想得以采用。Convention over Configuration就是指,“只要遵守一个适当的规约,即使不用进行非常麻烦的设定,框架结构也可以自动替我们搞定的思想”,这一思想是Ruby on Rails中所倡导的。Seasar2的Convention over Configuration是从Ruby on Rails 那里得到的提示而产生的。 将S2xxx.zip解压之后的seasar2目录引入到Eclipse、「文件→导入→既存的工程」。 使用Seasar2基本功能(S2Container, S2AOP)的时候、CLASSPATH的下面必须包含以下文件。
使用Seasar2的扩张机能(S2JTA, S2DBCP, S2JDBC, S2Unit, S2Tx, S2DataSet)的时候必须要将以下文件追加到CLASSPATH里面。
根据应用软件所需的执行环境、选择以下需要引用的文件[geronimo-j2ee_1.4_spec-1.0.jar、geronimo-jta_1.0.1B_spec-1.0.jar、geronimo-ejb_2.1_spec-1.0.jar]
为了让大家更简单的体验数据库机能、使用了HSQLDB作为RDBMS。为了能够体验Oracle机能、准备了hsql/sql/demo-oracle.sql。SQL*Plus等执行了之后、请根据环境的需要改写jdbc.dicon的XADataSourceImpl的设定项目。 想使用EJB3anoteshon的情况下、将 S2TigerXXX.zip解压缩后的s2-tiger目录引入Eclipse、「文件→导入→既存的工程」。 在Seasar2的设定基础上、必需要将以下的文件追加到CLASSPATH里面。
想使用Tigeranoteshon的情况、将S2TigerXXX.zip解冻后的s2-tiger目录引入Eclipse、「文件→进口→既存的项目」。 在Seasar2的设定基础上、必需要将以下的文件追加到CLASSPATH里面。
快速上手S2Container,就是进行Dependency Injection(注:依赖注入——译者)(以后略称为DI)的一个轻量级容器。DI,就是Interface和实装分离,程序相互之间仅通过Interface来会话的一种思考方式。 最初的一步让我们赶快试一试吧。登场人物如下。
Greeting.java问侯语的Interface。 package examples.di;
public interface Greeting {
String greet();
}
GreetingImpl.java问候语的实装。 package examples.di.impl;
import examples.di.Greeting;
public class GreetingImpl implements Greeting {
public String greet() {
return "Hello World!";
}
}
GreetingClient.java使用问候语的使用者客户端Interface。 package examples.di;
public interface GreetingClient {
void execute();
}
GreetingClientImpl.java使用问候语的客户端的实装。不是直接使用这个GreetngImpl(实装),而是通过Greeting(Interface)来实现问候的机能。 package examples.di.impl;
import examples.di.Greeting;
import examples.di.GreetingClient;
public class GreetingClientImpl implements GreetingClient {
private Greeting greeting;
public void setGreeting(Greeting greeting) {
this.greeting = greeting;
}
public void execute() {
System.out.println(greeting.greet());
}
}
机能提供端和使用端的准备都完成了。下面我们就执行一下试试吧。 GreetingMain.javapackage examples.di.main;
import examples.di.Greeting;
import examples.di.impl.GreetingClientImpl;
import examples.di.impl.GreetingImpl;
public class GreetingMain {
public static void main(String[] args) {
Greeting greeting = new GreetingImpl();
GreetingClientImpl greetingClient = new GreetingClientImpl();
greetingClient.setGreeting(greeting);
greetingClient.execute();
}
}
实行结果如下。 Hello World! 象这样机能的使用者(GreetingClientImpl)经由Interface(Greeting)的中介来使用机能,具体的机能对象(既Interface的实装类)在实行的时候由第三者(在这里是GreetingMain)来提供的情况,就是DI的基本思考方法。 但是,如果象GreetingMain中那样实装类的设定内容直接被写出来的话,一旦实装类需要变更的时候源代码也必须跟着修正。为了避免这个麻烦,DIContainer就登场了。把实装设定抽出到一个设定文件中,由DIContainer把这个设定文件读入并组织对象运行。 那么,让我们试着把刚才的提到的那个设定文件的内容写一下。S2Container中,设定文件的后缀是".dicon"。 GreetingMain2.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>
<component name="greeting"
class="examples.di.impl.GreetingImpl"/>
<component name="greetingClient"
class="examples.di.impl.GreetingClientImpl">
<property name="greeting">greeting</property>
</component>
</components>
<component name="greeting"
class="examples.di.impl.GreetingImpl"/>
上文记载的是组件的定义。在这里,相当于如下的Java代码。 Greeting greeting = new GreetingImpl(); component标签的name属性指定了组件的名称,class属性指定了组件的Java类文件名。下文就是greetingClient的设定。 <component name="greetingClient"
class="examples.di.impl.GreetingClientImpl">
<property name="greeting">greeting</property>
</component>
property标签的name属性指定了组件Java类中的属性名,标签的定义体则指定了一个组件名称。这个设定相当于如下Java代码。组件名要注意不要用["]括起来。用["]括起来的话就会被当作字符串来处理了。 GreetingClientImpl greetingClient = new GreetingClientImpl(); greetingClient.setGreeting(greeting); 利用S2Container的起动类的内容如下。 GreetingMain2.javapackage examples.di.main;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
import examples.di.GreetingClient;
public class GreetingMain2 {
private static final String PATH =
"examples/di/dicon/GreetingMain2.dicon";
public static void main(String[] args) {
S2Container container =
S2ContainerFactory.create(PATH);
container.init();
GreetingClient greetingClient = (GreetingClient)
container.getComponent("greetingClient");
greetingClient.execute();
}
}
S2Container,是由S2ContainerFactory#create(String path)做成的。更加详细的内容请参照S2Container的生成。 组件(greetingClient),是由S2Container#getComponent(String componentName)的方法取得的。详细内容请参照组件的取得。 实行结果同先前一样表示如下。 Hello World! 经常同DI一起使用的是AOP。AOP是指、将日志等的输出分散到复数个类中的逻辑模块化的一种技术。那么、让我们不修改已经作成的GreetingImpl、GreetingClinetImpl的源代码?试着将日志(追踪)输出。 适用于AOP的设定文件如下。 GreetingMain3.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="aop.dicon"/>
<component name="greeting"
class="examples.di.impl.GreetingImpl">
<aspect>aop.traceInterceptor</aspect>
</component>
<component name="greetingClient"
class="examples.di.impl.GreetingClientImpl">
<property name="greeting">greeting</property>
<aspect>aop.traceInterceptor</aspect>
</component>
</components>
Seasar2中,经常使用的AOP模块在aop.dicon中预先定义。 象下面这样、使用include标签。 更加详细的?敬请参照S2Container定义的分解和引入。 <include path="aop.dicon"/> 对于在组件中适用的AOP来说?我们component标签的字标签 aspect标签的正文中指定AOP的模块名称。aop.traceInterceptor是AOP模块的名字。 <aspect>aop.traceInterceptor</aspect> AOP的设定如上所述。那么就让我们执行一下GreetingMain3吧。同GreetingMain2不同的仅仅是设定文件的路径而已。 GreetingMain3.javapackage examples.di.main;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
import examples.di.GreetingClient;
public class GreetingMain3 {
private static final String PATH =
"examples/di/dicon/GreetingMain3.dicon";
public static void main(String[] args) {
S2Container container =
S2ContainerFactory.create(PATH);
GreetingClient greetingClient = (GreetingClient)
container.getComponent("greetingClient");
greetingClient.execute();
}
}
执行结果如下。可以明白一点,没有修改源代码,日志就被输出了。 DEBUG 2005-10-11 21:01:49,655 [main] BEGIN examples.di.impl.GreetingClientImpl#execute() DEBUG 2005-10-11 21:01:49,665 [main] BEGIN examples.di.impl.GreetingImpl#greet() DEBUG 2005-10-11 21:01:49,665 [main] END examples.di.impl.GreetingImpl#greet() : Hello World! Hello World! DEBUG 2005-10-11 21:01:49,675 [main] END examples.di.impl.GreetingClientImpl#execute() : null 这样、S2Container的基本使用方法就被掌握了。 更进一步但是,不管怎么说书写设定文件都是一件麻烦的事啊。在S2Container中,为了尽可能的减少设定文件的记述量、采用了如下的概念。 就是说制定一个适当的规约,遵守这个规约的话?无需什么设定也可以运作。比如说,刚才的设定文件中,象下面这样明确地指定属性的部分存在着。 <component name="greetingClient"
class="examples.di.impl.GreetingClientImpl">
<property name="greeting">greeting</property>
</component>
S2Container中、属性的类型是Interface的情形下? 如果要将属性类型的实装组件注册进软件容器中, 不需要什么特殊的设定也可以自动得运作DI的机能。 这就是,如果遵守DI中推荐的所谓“属性类型用Interface定义”的规则,S2Container会自动地处理一切。 虽然一说到规约就容易产生麻烦之类的想法,“推荐而已,如果遵守的话就能使开发愉快”的话,遵守规约的动机就产生了。这才是问题的重点。 如上的设定,可以做如下化简 <component name="greetingClient"
class="examples.di.impl.GreetingClientImpl">
</component>
实际上?刚才的AOP的例子也适用“Convention over Configuration”。 通常在AOP中,AOP的模块在什么地方适用是由pointcut指定的,S2AOP的情况下? 如果遵守所谓“使用Interface”这个推荐的规约,不指定pointcut,自动的适用于在Interface中定义的所有方法。因为有这个机能,在刚才的那个例子中,就没有必要指定pointcut。 虽然根据“Convention over Configuration”,DI和AOP的设定可以得以简化,需要处理的组件数增加了、仅仅组件的注册也会变成一个非常累的作业。那么这个组件注册自动化就叫做组件自动注册机能。 刚才的GreetingImpl、GreetingClientImpl的注册自动化如下。 <component
class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
FileSystemComponentAutoRegister组件将addClassPattern方法指定的类从文件系统中探寻出来,自动注册到S2Container中。关于initMethod标签,请参照方法函数注入。 addClassPattern方法的第一个参数是想要注册的组件的包的名字。 子包的内容也会用回归的方式检索。第二个参数是类的名字。可以使用正则表达式。也可以用“,”做分隔符指定复数个设定。 根据组件自动注册原则,即使后续追加组件的情况下,也没有必要追加设定,这样手续就大大地简化了。 如果组件的自动化注册可以了,接下来就会想让AOP的注册也自动化了吧。刚才的GreetingImpl、GreetingClientImp的AOP注册自动化的设定如下。 <include path="aop.dicon"/>
...
<component
class="org.seasar.framework.container.autoregister.AspectAutoRegister">
<property name="interceptor">aop.traceInterceptor</property>
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
用interceptor属性指定AOP的名称。addClassPattern方法同组件的自动化注册时的用法一样,这里就不做特殊的说明了。 组件自动化注册和AOP自动化注册的例子如下。 GreetingMain4.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="aop.dicon"/>
<component
class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
<component
class="org.seasar.framework.container.autoregister.AspectAutoRegister">
<property name="interceptor">aop.traceInterceptor</property>
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
</components>
那么来执行一下GreetingMain4吧。 自动注册的情况下,S2Container#init()和S2Container#destroy()的调用是必要的。 GreetingMain4.javapackage examples.di.main;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
import examples.di.GreetingClient;
public class GreetingMain4 {
private static final String PATH =
"examples/di/dicon/GreetingMain4.dicon";
public static void main(String[] args) {
S2Container container =
S2ContainerFactory.create(PATH);
container.init();
try {
GreetingClient greetingClient = (GreetingClient)
container.getComponent("greetingClient");
greetingClient.execute();
} finally {
container.destroy();
}
}
}
执行的结果同GreetingMain3一样如下列出。 DEBUG 2005-10-12 16:00:08,093 [main] BEGIN examples.di.impl.GreetingClientImpl#execute() DEBUG 2005-10-12 16:00:08,103 [main] BEGIN examples.di.impl.GreetingImpl#greet() DEBUG 2005-10-12 16:00:08,103 [main] END examples.di.impl.GreetingImpl#greet() : Hello World! Hello World! DEBUG 2005-10-12 16:00:08,103 [main] END examples.di.impl.GreetingClientImpl#execute() : null 大多数的情况下?自动注册和自动绑定的组合方式都能顺利的进行下去。不想要自动注册的组件存在的情况下,自动注册组件中准备了addIgnoreClassPattern方法,可以指定自动注册外的组件。 不想要自动绑定的属性存在的情况下,使用Binding备注码,不使用设定文件也可以做细节的调整。 使用Hotswap的话?应用程序在运行中重新书写更换类文件,马上就能够直接测试结果。不需要一个一个地将应用程序在启动,因此开发的效率能够得到大幅度的提高。 现在,关于S2Container的高级使用方法也可以掌握了。这之后嘛,只要根据需要参照对应的操作手册就可以了。 S2Container参考需要作成的文件为了使用S2Container,定义文件的做成是必要的。定义文件就像是为了组织组件而制作的设计书一样的东西。形式为XML,后缀为dicon。 S2Container的定义S2Container的定义、象下面这样。 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
"http://www.seasar.org/dtd/components23.dtd">
<components>
<component name="..." class="...">
...
</component>
<component name="..." class="...">
...
</component>
</components>
DOCTYPE是不能省略的。dicon做成的时候、请将前述例子拷贝粘贴。根是components标签。每一个组件用component标签定义。用component标签的class属性指定组件的类的全名。在name属性中、指定组件的名称。详细内容请参照S2Container定义标签参考。 <components>
<component name="hoge" class="examples.dicon.HogeImpl"/>
</components>
S2Container的生成S2Container的生成方法有两种。
使用SingletonS2ContainerFactory使用SingletonS2ContainerFactory的情况下,使用如下方法。 - org.seasar.framework.container.factory.SingletonS2ContainerFactory#init() 定义文件使用的是CLASSPATH所指定的路径中存在的app.dicon。 做成的S2Container,无论在什么地方都是可以从如下方法中取得。 - org.seasar.framework.container.factory.SingletonS2ContainerFactory#getContainer() SingletonS2ContainerFactory.init(); ... S2Container container = SingletonS2ContainerFactory.getContainer(); 定义文件的路径需要被指定的情况下应在调用init()之前执行如下方法。 - org.seasar.framework.container.factory.SingletonS2ContainerFactory#setConfigPath(String Path) 参数path是相对于以CLASSPATH指定的路径为根的定义文件的绝对路径。例如,WEB-INF/classes/aaa.dicon 的情况下就是aaa.dicon,WEB-INF/classes/aaa/bbb/ccc.dicon的情况下就是aaa/bbb/ccc.dicon。分隔符在Windows和Unix下都是/。 private static final String PATH = "aaa/bbb/ccc.dicon"; ... SingletonS2ContainerFactory.setConfigPath(PATH); SingletonS2ContainerFactory.init(); ... S2Container container = SingletonS2ContainerFactory.getContainer(); 使用S2ContainerFactory使用S2ContainerFactory的场合下,使用如下方法。 - org.seasar.framework.container.factory.S2ContainerFactory#create(String path) S2Container生成之后需要许呼叫下一个方法。 - org.seasar.framework.container.S2Container#init() private static final String PATH = "aaa/bbb/ccc.dicon"; ... S2Container container = S2ContainerFactory.create(PATH); container.init(); 用这个方法取得的组件的实例,有必要进行在应用中的管理。 组件的取得从S2Container中将组件取出来,使用下面的方法。 - org.seasar.framework.container.S2Container#getComponent(Object componentKey) 参数中指定的是组件的类或者是组件的名称。详细的请参照component标签。要指定组件的类,只要是 组件 instanceof 类 的操作返回为true的类就能够指定。但是、S2Container中所指定的类对应了好几个实装的组件的时候,S2Container将不能判断返回哪一个组件为好,这样就会发生TooManyRegistrationRuntimeException。请指定实装组件为唯一的类。也可以用组件名称取得组件。这种情况下也是同样,用一个名称的复数个组件被注册的情况下,将发生TooManyRegistrationRuntimeException。指定组件名的场合下,因为也可能发生拼写错误,所以尽可能的指定组件的类为好。 例)通过指定类来取得组件的场合 S2Container container = S2ContainerFactory.create(PATH); Hoge hoge = (Hoge) container.getComponent(Hoge.class); 例)通过指定组件名来取得组件场合 S2Container container = S2ContainerFactory.create(PATH);
Hoge hoge = (Hoge) container.getComponent("hoge");
Dependency Injection的类型在Dependency Injection中,组件的构成所必要的值是用构造函数来设定(Constructor Injection),还是用设定函数来设定(Setter Injection),或者是用初始化函数来设定(Method Injection),这样进行分类。Method Injection是S2Container的本源。S2Container支持以上所有类型和混合类型。 构造函数?注入对构造函数的参数进行DI,这就是构造函数注入。
<components>
<component name="..." class="...">
<arg>...</arg>
</component>
</components>
设定函数?注入设定函数注入是指对于任意一个属性变量使用设定函数来行使DI。
<components>
<component name="..." class="...">
<property name="...">...</property>
</component>
</components>
方法函数?注入方法函数注入是指,通过任意一个函数的调用来完成DI的功能。
<components>
<component name="..." class="...">
<initMethod name="...">
<arg>...</arg>
</initMethod>
</component>
</components>
S2Container定义的分割和引入所有的组件用一个文件来设定的话,很快就会变得臃肿而难以管理。因此,S2Container就具有了将组件的定义进行复数个分割的机能和将多个分割的定义文件引入而组织成一个文件的机能。S2Container定义文件的引入方法如下。 <components>
<include path="bar.dicon"/>
</components>
include标签的path属性被用来指定想要引入的S2Container定义文件的路径。详细情况请参照include标签。 <components>
<include path="aaa.dicon"/>
<include path="bbb.dicon"/>
<component class="example.container.Foo" />
</components>
命名空间组件的定义被分割的情况下,为了不让复数个组件的定义名称发生冲突,可以用components标签的namespace属性指定命名空间。 foo.dicon<components namespace="foo">
<component name="aaa" .../>
<component name="bbb" ...>
<arg>aaa</arg>
</component>
</components>
bar.dicon<components namespace="bar">
<include path="foo.dicon"/>
<component name="aaa" .../>
<component name="bbb" ...>
<arg>aaa</arg>
</component>
<component name="ccc" ...>
<arg>foo.aaa</arg>
</component>
</components>
app.dicon<components>
<include path="bar.dicon"/>
</components>
在同一个组件定义文件中可以不需要指定命名空间而调用组件。调用其它S2Container文件中定义的组件时,要在组件名前加上命名空间。foo.aaa 和 bar.aaa 虽然有相同名称的组件,但是因为命名空间的不同,就被认为是不同的组件。 实例(instance)管理在S2Container中,怎么样对实例进行管理,这个设定是用component标签的instance属性。
生存周期使用initMethod 和 destroyMethod组件的生存周期也可以用容器来管理。在S2Container的开始时用(S2Container.init())调用initMethod标签中指定的方法,S2Container结束时用(S2Container.destroy())调用destroyMethod标签中指定的方法。initMethod将按照容器中注册的组件的顺序来执行组件,destroyMethod则按照相反的顺序去执行。instance属性是singleton之外的情况下,指定了destroyMethod也会被忽视。java.util.HashMap#put()方法中初始化(给aaa赋值为111)?结束处理(给aaa赋值为null)的设定,向下面那样。 <components namespace="bar">
<component name="map" class="java.util.HashMap">
<initMethod name="put">
<arg>"aaa"</arg>
<arg>111</arg>
</initMethod>
<destroyMethod name="put">
<arg>"aaa"</arg>
<arg>null</arg>
</destroyMethod>
</component>
</components>
自动绑定组件间的依存关系,类型是interface的场合时,将由容器来自动解决。这是在S2Container被默认的,指定component标签的autoBinding属性可以进行更加细致的控制。
构造函数的自动绑定规则如下所示。
属性变量的自动绑定规则如下。
用property标签的bindingType属性,可以更加细致的控制属性变量。
在组件中利用S2Container不想让组件依存于S2Container的情况下,根据组件的具体情况,在组件中需要调用S2Container的方法,这样的场合也许会存在。S2Container自身也以container的名称,自我注册了。所以可以在arg,property标签的正文中指定container,从而取得容器的实例。还有,S2Container类型的setter方法定义好了后也可以做自动绑定的设定。用arg,property标签指定container的情况下,向下面这样进行。 <components>
<component class="examples.dicon.BarImpl">
<arg>container</arg>
</component>
<component class="examples.dicon.FooImpl">
<property name="foo">container</property>
</component>
</components>
S2ContainerServlet到此为止,在Java application中,是用明确表示的方法做成S2Container的,Web application的情况下,由谁来作成S2Container呢?为了达到这个目的,准备了以下的类。
为了使用S2ContainerServlet,在web.xml中记述如下项目。 <servlet>
<servlet-name>s2servlet</servlet-name>
<servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class>
<init-param>
<param-name>configPath</param-name>
<param-value>app.dicon</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>s2servlet</servlet-name>
<url-pattern>/s2servlet</url-pattern>
</servlet-mapping>
用configPath来指定作为根的S2Container的定义路径。定义文件将放在WEB-INF/classes中。对于S2ContainerServlet,为了比其它的servlet更早的起动,请做load-on-startup标签的调整。S2ContainerServlet起动之后,可以用如下的方法函数取得S2Container的实例。
另外,S2Container的生命周期和S2ContainerServlet是连动的。debug变量被设为true的话,按照以下的方法,可以将运行中的S2Container再次起动。xxx是Web application的context名。 http://localhost:8080/xxx/s2servlet?command=restart
在使用了S2ContainerServlet的情况下,ServletContext将会作为一个组件可以用servletContext的名字来访问。 app.dicon的角色根的S2Container的定义文件,按照惯例用app.dicon的名称。通常放在WEB-INF/classes中就好了。 AOP的适用在组件中AOP的适用情况也可以被设定。比如,想要在ArrayList中设定TraceInterceptor使用的情况下需要象下面这样做。 <components>
<component name="traceInterceptor"
class="org.seasar.framework.aop.interceptors.TraceInterceptor"/>
<component class="java.util.ArrayList">
<aspect>traceInterceptor</aspect>
</component>
<component class="java.util.Date">
<arg>0</arg>
<aspect pointcut="getTime, hashCode">traceInterceptor</aspect>
</component>
</components>
aspect标签的正文中指定Interceptor的名字。pointcut的属性中可以用逗号做分隔符指定AOP对象的方法的名字。pointcut的属性没有被指定的情况下,组件将把实装的interface的所有方法函数作为AOP的对象。方法函数的名称指定也可以用正则表达式(JDK1.4のregex)。这样的定义例子如下。 private static final String PATH =
"examples/dicon/Aop.dicon";
S2Container container = S2ContainerFactory.create(PATH);
List list = (List) container.getComponent(List.class);
list.size();
Date date = (Date) container.getComponent(Date.class);
date.getTime();
date.hashCode();
date.toString();
执行结果。 BEGIN java.util.ArrayList#size() END java.util.ArrayList#size() : 0 BEGIN java.util.Date#getTime() END java.util.Date#getTime() : 0 BEGIN java.util.Date#hashCode() BEGIN java.util.Date#getTime() END java.util.Date#getTime() : 0 END java.util.Date#hashCode() : 0 BEGIN java.util.Date#getTime() END java.util.Date#getTime() : 0 组件中也可以设定InterType的适用情况。比如,在Hoge中设定PropertyInterType的适用情况如下进行。 <components>
<include path="aop.dicon"/>
<component class="examples.Hoge">
<interType>aop.propertyInterType</aspect>
</component>
</components>
在interType标签的正文中指定InterType的名称。 Meta数据在components、component、arg、property标签中也可以指定Meta数据。meta标签将作为需要指定Meta数据的标签的字标签来指定Meta数据。例如,想要在components标签中指定Meta数据的情况时,象下面一样设定。 <components>
<meta name="aaa">111</meta>
</components>
request的自动绑定对于组件来说,也可以进行HttpServletRequest的自动绑定。为了实现这个目的,在组件中,定义了setRequest(HttpServletRequest request)方法。这样的话,S2Container就自动得设定了request。还有,需要象下面这样在web.xml中进行Filter的定义。 <web-app>
<filter>
<filter-name>s2filter</filter-name>
<filter-class>org.seasar.framework.container.filter.S2ContainerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>s2filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
同样地对HttpServletResponse、HttpSession、ServletContext也是只要定义了setter方法,就可以自动绑定了。而且,使用了S2ContainerFilter的话,HttpServletRequest、HttpServletResponse、HttpSession、ServletContext就可以各自用request、response、session、application的名字来做为组件被自由访问了。 组件的自动注册根据自动绑定的原理,DI的设定几乎可以做近乎全部的自动化。 使用备注码就有可能进行更加细致的设定。 更进一步、对组件的注册也进行自动化的话,就可以称为组件的自动注册机能了。 org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister是从文件系统中将类检索出来对组件进行自动注册的组件。
org.seasar.framework.container.autoregister.JarComponentAutoRegister从Jar文件中检索类自动注册组件的组件。
org.seasar.framework.container.autoregister.ComponentAutoRegister将类从文件系统或者Jar文件中检索出来并将组件自动注册的组件。
AutoNaming根据AutoNaming来控制组件名称。 org.seasar.framework.container.autoregister.DefaultAutoNaming从类的完整合法名称中将类的包的那部分名称去掉,如果结尾是Impl或者Bean也要去掉,之后将开头的字母变成小写做为组件名称来设定。 例如,aaa.HogeImpl类的情况下,组件的名称就成了hoge。
org.seasar.framework.container.autoregister.QualifiedAutoNaming将包的名字或者是一部分类的合法名做为组件名称的设定。从类的完整合法名的最后把Impl或者Bean去掉,开头字母小写,分隔点后紧接着的字母变成大写并取掉分隔点,将这个新的单词设定为组件的名称。
例<component
class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
<property name="autoNaming">
<component class="org.seasar.framework.container.autoregister.DefaultAutoNaming">
<initMethod name="setCustomizedName">
<arg>"examples.di.impl.HogeImpl"</arg>
<arg>"hoge2"</arg>
</initMethod>
</component>
</property>
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
<component class="org.seasar.framework.container.autoregister.JarComponentAutoRegister">
<property name="referenceClass">
@junit.framework.TestSuite@class
</property>
<property name="jarFileNames">"junit.*"</property>
<initMethod name="addClassPattern">
<arg>"junit.framework"</arg>
<arg>"TestSuite"</arg>
</initMethod>
</component>
<component class="org.seasar.framework.container.autoregister.ComponentAutoRegister">
<initMethod name="addReferenceClass">
<arg>@aaa.bbb.ccc.ddd.HogeImpl@class</arg>
</initMethod>
<initMethod name="addClassPattern">
<arg>"aaa.bbb"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
AOP的自动注册根据组件的自动注册规则,组件的注册可以做到自动化。进一步,AOP的注册也可以做到自动化,这就是AOP的自动注册机能。 和组件的自动注册功能组和使用的场合下,必须在组件的自动注册设定之后,作AOP的自动注册的设定。对于适用于使用AOP的组件的记述,必须在AOP的自动注册设定之后进行。 <components>
<!-- 1.组件的自动注册 -->
<component class="org.seasar.framework.container.autoregister.ComponentAutoRegister">
...
</component>
<!-- 2.AOP的自动注册 -->
<component class="org.seasar.framework.container.autoregister.AspectAutoRegister">
...
</component>
<!-- 3.其它的组件 -->
<component class="...">
...
</component>
...
<components>
org.seasar.framework.container.autoregister.AspectAutoRegister通过指定类名的模式来进行AOP的自动注册的组件。
例<include path="aop.dicon"/>
...
<component
class="org.seasar.framework.container.autoregister.AspectAutoRegister">
<property name="interceptor">aop.traceInterceptor</property>
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
org.seasar.framework.container.autoregister.InterfaceAspectAutoRegister针对某个interface的实装类进行AOP的自动注册的组件。
例<include path="aop.dicon"/>
...
<component
class="org.seasar.framework.container.autoregister.InterfaceAspectAutoRegister">
<property name="interceptor">aop.traceInterceptor</property>
<property name="targetInterface">@examples.Greeing@class</property>
</component>
META的自动注册META信息也可以自动注册。 同组件的自动注册相组合使用的场合下,必须在组件的自动注册设定之后,做META的自动注册的设定记述。 调用META信息的组件必须在META自动注册的设定之后记述。 <components>
<!-- 1.组件的自动注册 -->
<component class="org.seasar.framework.container.autoregister.ComponentAutoRegister">
...
</component>
<!-- 2.META的自动注册 -->
<component class="org.seasar.framework.container.autoregister.MetaAutoRegister">
...
</component>
<!-- 3.其它的组件 -->
<component class="...">
...
</component>
...
<components>
org.seasar.framework.container.autoregister.MetaAutoRegister通过指定类名的模式来做META自动注册的组件。
例<component
class="org.seasar.framework.container.autoregister.MetaAutoRegister">
<meta name="autoRegister">
<meta name="hoge"</meta>
</meta>
<initMethod name="addClassPattern">
<arg>"examples.di.impl"</arg>
<arg>".*Impl"</arg>
</initMethod>
</component>
本例中、叫做hoge的META数据自动地注册到其它的组件定义中。 Hotswap一直以来,更改了源代码并重新编译之后的场合,想要测试编译后的机能,必须让应用程序(确切地说是ClassLoader)再起动。在应用程序服务器上,进行程序再起动将非常花时间。 “真烦人”这样想的人很多不是吗。 在Seasar2中,应用程序在运行中,即使类文件替换了,也可以即刻测试的Hotswap机能得以实现。这样就让我们从那种“心情烦躁”中解放出来了。无须花费多余的时间使得出产率得以提高。这样的好东西,不想试一试吗? Greeting.javapackage examples.hotswap;
public interface Greeting {
String greet();
}
GreetingImpl.javapackage examples.hotswap.impl;
import examples.hotswap.Greeting;
public class GreetingImpl implements Greeting {
public String greet() {
return "Hello";
}
}
hotswap.dicon<components>
<component class="examples.hotswap.impl.GreetingImpl"/>
</components>
到此为止,并没有什么特别的变化。关键点从此开始。 使用s2container.dicon,切换成hotswap模式。 s2container.dicon&l 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
最后更新时间:2008-05-14
还是有参考价值的。
看来日本人在自由思维上也算不错了 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
最后更新时间:2008-05-15
楼主辛苦了,
这个框架太。。。太适合快速开发了。 呵呵 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
最后更新时间:2008-05-25
请教一下,teeda的session怎么取得的?
比如我在struts里面是通过request.getHttpSession()取得session对象, |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
最后更新时间:2008-07-15
将GreetingClientImpl.java中的
private Greeting greeting改为public Greeting greeting 那个错误可解决 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
浏览 1974 次




