Seasar2 中文——快速入门

快速入门

seasar2是一个依赖注入(DI)操作的轻量级容器。

第一步

让我们试试看,将使用下列对象。

  1. Greeting Class
    返回一个问候字符串。

  2. Greeting Client Class
    输出从问候类到控制台的字符串。

  3. Greeting Main Class
    启动类。还构造问候和问候客户端类。

Greeting.java

Greeting interface.

package examples.di;

public interface Greeting {

    String greet();
}

GreetingImpl.java

Getting的实现

package examples.di.impl;

import examples.di.Greeting;

public class GreetingImpl implements Greeting {

    public String greet() {
        return "Hello World!";
    }
}

GreetingClient.java

使用Getting的客户端接口

package examples.di;

public interface GreetingClient {

    void execute();
}

GreetingClientImpl.java

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.java

package 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!

如上所示,是DI的基本风格。

However, if one writes configurations into the source as GreetingMain, the source code must be altered to reflect any changes. DIContainer is used to avoid this. DIContainer constructs objects by reading external configuration files.

我们将会把配置信息写入配置文件中。在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="greetingClient"
    class="examples.di.impl.GreetingClientImpl">
    <property name="greeting">greeting</property>
</component>

等价于

GreetingClientImpl greetingClient = new GreetingClientImpl();
greetingClient.setGreeting(greeting);

下面使用S2Container方式启动程序:
GreetingMain2.java

package 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);
        GreetingClient greetingClient = (GreetingClient)
            container.getComponent("greetingClient");
        greetingClient.execute();
    }
}

S2Container 通过 S2ContainerFactory#create(String Path) 被创建。
组件(greetingClient)通过S2Container#getComponent(String componentName)被获取。

其运行结果如下:

Hello World!

AOP经常和DI一起使用,AOP是指将日志等的输出分散到复数个类中的逻辑模块化的一种技术。我们将从 GreetingImpl中输入一个log (trace),但是却不改变GreetingClientImpl 现有的源代码。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 path="aop.dicon"/>

我们在组件中定义标签应用AOP,在body中指定AOP的模块名,我们将使用aop.traceInterceptor作为模块名。

<aspect>aop.traceInterceptor</aspect>

这就是AOP配置的结论。现在我们试着运行GreetingMain3,与GreetingMain2仅在配置文件的路径有所差异。

GreetingMain3.java

package 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();
    }
}

运行结果如下,我们看到log的输出并没有改变原来的代码。

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还具有以下概念来减少配置文件中的文字。

  • Convention over Configuration

这实现了一些公约,因此,一些程序可以离开配置运行,只要它遵守这些规定,举个例子,之前的配置文件明确定义属性标记如下:

<component name="greetingClient"
    class="examples.di.impl.GreetingClientImpl">
    <property name="greeting">greeting</property>
</component>

只要属性类型是一个接口,并且在容器中有一个接口的实现,S2Container 有自动DI的功能。这意味着S2Container将自动处理组件,只要他们遵循接口定义属性类型的DI约定。

“公约”听起来很烦人,但它们不仅被推荐,而且使开发更容易。

我们可以从上面简化配置如下:

<component name="greetingClient"
    class="examples.di.impl.GreetingClientImpl">
</component>

其实,“公约优先于配置”很早就在AOP中被运用。通常情况下,在AOP模块被应用的地方或方法定义切入点。ll methods defined by interface have the AOP module applied without the use of pointcut in S2AOP as long as they follow the convention of using interface. 这就是为什么在前面例子中没有必要定义一个模块的切入点。

在配置使用公约将简化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>

在S2Container中,这个 FileSystemComponentAutoRegister 组件从file system 中搜索在 addClassPattern 中被定义的类,并自动注册他们

addClassPattern方法中的第一个参数是自动注册组件的包名,递归搜索子包。第二个参数是类的名字,可能是正则表达式,多个定义用逗号隔开。

组件的自动注册减少了总工作量,因为程序猿不需要配置新的组件。

当我们自动化组件的注册,下一个重点就是自动化方面的注册,GreetingImpl 和 GreetingClientImp的Aspect自动注册的配置文件如下:

<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 方法的解释,因为它与组件自动注册相同。组件和面的自动注册的结合,看起来如下

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.java

package 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 method 从自动注册中排除。

绑定注释可用于微调配置设置,而无需使用配置文件以排除自动绑定的属性。

热插拔可立即重试不重新启动应用程序,开发更高效。

现在我们已经掌握了先进的使用s2container。请根据需要参考手册。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值