日志文章

2007年11月02日 15:13:04

利用轻量级容器提供企业服务

利用轻量级容器提供企业服务
业务“需要”重量级架构(比如 Enterprise Java™Beans (EJB)技术)提供的企业服务,但这种架构对于解决日常问题可能过于复杂。本文介绍轻量级容器,并解释它们如何提供满足您业务需要的服务,而无需将您束缚在一个指定的编程模型之上。

1. 什么是轻量级容器

大多数容器 API(如 EJB API)强迫您编写一些接口或一个组件模型。将您的组件放入该容器后,容器会为您处理一些事情。EJB 容器提供企业服务。Servlet 容器(例如 Apache Jakarta Tomcat)实现了 Servlet API,使您可以将动态内容建立到服务器页面中,该页面随后会被发送到 Web 浏览器。

传统容器强迫使用指定的编程模型,轻量级容器则不是。它们使用普通 Java 对象(plain old Java objectPOJO)。容器然后将 POJO 绑在一起,并将服务与它们相关联。轻量级容器的共同特征包括:

Ø     基于 POJO 的编程 —— 轻量级容器不具侵犯性。它不强迫执行任何 API

Ø     生命周期管理 —— 轻量级容器管理放入其中的对象的生命周期。最低限度下,它们实例化并销毁对象。

Ø     依赖性解析 —— 轻量级容器提供了一个普通的依赖性解析策略。多数容器现在支持称为依赖注入的策略。还有一些支持 Java 2 平台企业版(J2EE)风格的策略,称之为服务定位。

Ø     一致的配置 —— 轻量级容器是一个便于提供一致配置服务的位置。

Ø     服务关联 —— 轻量级容器提供一种将服务与容器中的对象相关联的方法。

2. 优点

轻量级容器有许多胜于其他容器架构的优点。例如,您可以使用一个更加简单、基于 POJO 的编程模型。使用 POJO 编程,应用程序会更加易于测试。您的对象也可以在容器外运行 —— 例如,在一个测试用例中。通过依赖注入,轻量级容器减少了组件间的依赖性。它们也保护了您在代码上花费的心血,因为您可以在容器间移动应用程序的大部分。特别是业务实现业务逻辑的程序。

3. 依赖注入

Java 技术中,依赖注入正迅速地改变我们构建应用程序的方式。这种概念相对简单:一个消费者(类似下面的 Consumer 类)需要一个服务。您为指向该服务(类似下面的 Speaker 类)的消费者添加一个属性(You add a property to the consumer that points to the service (like the Speaker class below).)。清单 1 展示了此概念的示例。

清单 1. 依赖注入的示例

class Speaker {
void speak(String words) {
  System.out.println(words);
}
}
class Consumer {
Speaker mySpeaker;
void saySomething() {
  mySpeaker.speak("I speak Chinese");
}
}

请注意 Consumer 类。它没有实例化 Speaker 类。有了依赖注入,该工作就由称之为 Container 类(参阅清单 2)的第三方来处理。
清单 2. Container

class Container {
public static void main(String[] args) {
  Speaker speaker=new Speaker();
  Consumer consumer=new Consumer();
  consumer.speaker = speaker;
  consumer.saySomething();
}
}

Container 类实例化了 Speaker Consumer 类。然后 Container 类将 speaker 属性设置为新的 Speaker 类。最后一步表示依赖注入。

4. 接口的强大功能
让我们稍微对上述段代码进行重构。构建一个称为 Speaker 的接口和两个不同的实现:一个 EnglishSpeaker 和一个FrenchSpeaker假设它们的作用是把你所说的话翻译生成英语或法语。因此,您现在拥有了 Speaker 接口:

interface Speaker {
void speak(String words);
}



EnglishSpeakerFrenchSpeaker

public class EnglishSpeaker implements Speaker {

public void speaker(String words) {

      System.out.println(words+" Your speach will be trnslated into English.");

}

}



public class FrenchSpeaker implements Speaker {

public void speaker(String words) {

      System.out.println(words+" Your speach will be trnslated into Frenchh.");

}

}



容器:

public class Container {

public static void main(String[] args) {

    Speaker mySpeaker=new FrenchSpeaker();

    Consumer consumer=new Consumer();

    consumer.mySpeaker=mySpeaker;

    consumer.saySometing();

}

}

注意,您现在可以在 speaker 的两个实现之间变化,而惟一需要改变的代码就是容器。更关键的是,您可以轻松地注入模拟对象来替代真正的 Speaker 实现,并且无需影响其他的代码就可以进行测试。如果需要翻译成西班牙、葡萄牙语….等,只要加相应的实现即可,原来的代码无须任何改变。符合OCP原则吧!还有要针对接口编程不要针对类进行编程等的面向对象设计原则。
但是在这种情况下,如果我要翻译成英语还是要修改容器的代码,有没有一种方法可以不用修改任何代码呢?这个就可以通过下述的利用SpRING框架的方法来实现。
当然,最终目标是用专门定制的容器来替代这个手写容器。例如,使用 Spring 容器。在本例中,替换的是您的 Container 类,并且您可以使用类似清单 3 中代码的简单 XML 文件。





清单 3. 用于 Spring 容器的 XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
   
  <bean id="speaker" class="org.chenb.FrenchSpeaker" abstract="false"
    singleton="true" lazy-init="default" autowire="default"
    dependency-check="default">    
  </bean>  
 
  <bean id="consumer" class="org.chenb.Consumer">
    <property name="mySpeaker"><ref bean="speaker"/></property>
  </bean>
 
</beans>

Consumer类:

public class Consumer {

Speaker mySpeaker;

public Speaker getMySpeaker() {

    return mySpeaker;

}

public void setMySpeaker(Speaker mySpeaker) {

    this.mySpeaker = mySpeaker;

}

    void saySomething(){

    mySpeaker.speaker("The speach");

}

}



容器:

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.FileSystemXmlApplicationContext;

public class Container {

public static void main(String[] args) {

  ApplicationContext context = new FileSystemXmlApplicationContext("org/chenb/applicationContext.xml");

Consumer consumer = (Consumer)context.getBean("consumer");

consumer.getMySpeaker().speaker("The speach");

}

}



Spring 容器与您的容器完成相同的事情。它实例化 beans,并通过设置属性而将它们绑在一起。注意,两部分代码是完全去耦的;接口和容器确保了这一点。您可以使用依赖注入来满足进行企业级开发(例如,数据源或事务管理器)所遇到的许多依赖性。现在如果需要翻译成西班牙、葡萄牙语….等,添加相应的实现不用在去修改“容器”的,只需要修改.xml文件就可以了。
应用程序的固有层次之间自然地相互依赖。您可能拥有一个由控制器调用的 Web 用户界面(UI)视图,它调用外观层,外观层调用数据访问对象,数据访问对象调用对象关系映射,对象关系映射调用数据库。这些关系就是依赖性。如果能将它们解耦,会更加易于编码、测试和维护。















类别: 开发 |  评论(0) |  浏览(4593) |  收藏
发表评论
看不清楚,换一张