
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 object,POJO)。容器然后将 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); }EnglishSpeaker和FrenchSpeaker: 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> 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 条评论