反转控制的几个重要好处

倒置控制的几个重要好处。如:
. 因为组件不需要在运行时间寻找合作者,所以他们可以更简单的编写和维护。在Spring的IoC版本里,组件通过暴露JavaBean的setter方法表达他们依赖的其他组件。这相当于EJB通过JNDI来查找,EJB查找需要开发人员编写代码。
. 同样原因,应用代码更容易测试。JavaBean属性是简单的,Java核心的,并且容易测试:仅编写一个包含自身的Junit测试方法用来创建对象和设置相关属性即可。
. 一个好的IoC实现隐藏了强类型。如果你使用一个普通的factory来寻找合作者,你必须通过类型转换将返回结果转变为想要的类型。这不是一个主要问题,但是不雅观。使用IoC,你在你的代码中表达强类型依赖,框架将负责类型转换。这意味着在框架配置应用时,类型不匹配将导致错误;在你的代码中,你无需担心类型转换异常。
. 大部分业务对象不依赖于IoC容器的APIs。这使得很容易使用遗留下来的代码,且很容易的使用对象无论在容器内或不在容器内。例如,Spring用户经常配置Jakarta Commons DBCP数据源为一个Spring bean:不需要些任何定制代码去做这件事。我们说一个IoC容器不是侵入性的:使用它并不会使你的代码依赖于它的APIs。任何JavaBena在Spring bean factory中都能成为一个组件
最后应该强调的是,IoC 不同于传统的容器的体系结构( 如EJB), 应用代码最小程度的依靠于容器。这意味着你的业务对象可以潜在的被运行在不同的IoC 框架上-或者在任何框架之外-不需要任何代码改。
以我的经验和作为Spring用户,过分强调IoC给应用代码带来的好处是不容易的。
IoC不是一个新概念,但是它在J2EE团体里面刚刚到达黄金时间。 有一些可供选择的IoC 容器: notably, Apache Avalon, PicoContainer 和 HiveMind. Avalon 不会成为特别流行的,尽管它很强大而且有很长的历史。Avalon是相当的重量级和复杂的,并且看起来比新的IoC解决方案更具侵入性。 PicoContainer是一个轻量级而且更强调通过构造器表达依赖性而不是JavaBean 属性。 与Spring不同,它的设计允许每个类型一个对象的定义(可能局限性结果来自它对Java代码外的元数据的拒绝)。作为和Spring and PicoContainer and other IoC frameworks的比较,可参看文章http://www.springframework.org/docs/lightweight_container.html. 这个业面包含了PicoContainer站点链接 。
Spring BeanFactories 是非常轻量级的。用户已经成功地将他们应用在applets中和单独的Swing应用中。(它们也很好地工作在EJB容器中。) 没有特殊的部署步骤和可察觉的启动时间。这个能力表明一个容器在应用的任何层面差不多立即可以发挥非常大的价值。
Spring BeanFactory 概念应用贯穿于Spring整体, 而且是Spring如此内在一致的关键原因。在IoC容器中,Spring也是唯一的,它使用IoC作为基础概念贯穿于整个框架。
对应用开发人员,最重要的是,一个或多个BeanFactory提供一个定义明确的业务对象层。这是类似的,但比local session bean层更简单。与EJBs不同,在这个层中的对象可能是相关的,并且他们的关系被自己的factory管理。有一个定义明确的业务对象层对于一个成功的体系结构是非常重要的。
Spring ApplicationContext 是BeanFactory的子接口,为下列提供支持:
.消息寻找,国际化支持
.事件机制,允许应用对象发布和随意地注册为事件监听
.便携文件和资源访问
XmlBeanFactory示例
Spring用户通常在XML“bean定义”文件中配置他们的应用。Spring的XML bean定义文档的根是一个<beans> 元素。该元素包含一个或多个 <bean>定义。我们一般指定一个bean定义的类和属性。我们也必须指定ID作为标识,我们将在代码中使用该标志。
让我们来看一个简单的例子,在J2EE应用中常看到用来配置三个应用对象:
. J2EE DataSource
. 使用DataSource的DAO
. 在处理过程中使用DAO的业务对象
在下面的例子中,我们使用一个来自Jakarta Commons DBCP项目的BasicDataSource。这个class(和其他存在的class一样)可以简单地被应用在Spring bean factory中,因为它提供了JavaBean格式的配置。需要在shutdown时被调用的Close方法可通过Spring的"destroy-method"属性被注册,来避免BasicDataSource需要实现任何Spring 接口。
代码:
<beans>
    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>
        <property name="url"><value>jdbc:mysql://localhost:3306/mydb</value></property>
        <property name="username"><value>root</value></property>
    </bean>
我们感兴趣的BasicDataSource的所有属性都是String型的,因此,我们用<value>元素来指定他们的值。如果必要的话,Spring使用标准的 JavaBean属性编辑器机制来转换String以表示其他的类型。
现在,我们定义了DAO,它有一个对DataSource的bean引用。Bean间关系通过<ref>元素来指定:
代码:
<bean id="exampleDataAccessObject" class="example.ExampleDataAccessObject">
        <property name="dataSource">
            <ref bean="myDataSource"/>
        </property>
    </bean>
业务对象有一个DAO的引用和一个int型属性(exampleParam):
代码:
<bean id="exampleBusinessObject" class="example.ExampleBusinessObject">
        <property name="dataAccessObject"><ref bean="exampleDataAccessObject"/></property>
        <property name="exampleParam"><value>10</value></property>
    </bean>
</beans>
对象间的关系一般在配置中明确地设置,象此例子一样。我们认为这样做是件好事情。无论如何,Spring也提供了我们叫做"autowire"的支持, 一个la PicoContainer,在那里,它可以指出bean间的依赖关系。这样做的局限性-如使用PicoContainer-是如果有一个特殊类型的多个Bean,要作出一个类型应该与哪个实例相关的判断将是不可能的。好的方面,在factory初始化后,不理想的依赖可能会被捕获到。(Spring 也为清楚的配置提供一种可选的依赖检查,它可以完成这个目的)
如果我们不想明确的编写他们的关系,在上面的例子中,我们可如下使用autowire特性
<bean id="exampleBusinessObject" class="example.ExampleBusinessObject" autowire="byType">
<property name="exampleParam"><value>10</value></property>
</bean>
使用这用用法,Spring将找出exampleBusinessObject的dataSource属性应该被设置为在当前BeanFactory中找到的DataSource实现。在当前的BeanFactory中,如果所需要类型的bean不存在或多于一个,将产生一个错误。我们依然要设置exampleParam属性,因为它不是一个引用。
Autowire支持和依赖检查刚刚加入CVS并将在Spring 1.0 M2(到10/20,2003)中提供。本文中所讨论的所有其他特性都包含在当前1.0 M1版本中。
来自Java代码的外在关系比硬编码有极大的好处,因为改变XML文件而无需改变一行Java代码是可能的。例如,我们可以简单地改变myDataSource的bean定义来提供不同的bean class以使用一个可供选择的连接池,或者一个测试数据源。 在一个单独可选的XML片断中,我们可以用Spring的JNDI 定位FactoryBean来从application server获取一个数据源。
现在让我们来看例子中业务对象的java 代码。注意下面列出的代码中没有对Spring的依赖。不像EJB容器,Spring BeanFactory不是侵入性的:在应用对象里面你通常不需要对他们编码。
代码:
public class ExampleBusinessObject implements MyBusinessObject {
   private ExampleDataAccessObject dao;
   private int exampleParam;
   public void setDataAccessObject(ExampleDataAccessObject dao) {
      this.dao = dao;
   }
   public void setExampleParam(int exampleParam) {
      this.exampleParam = exampleParam;
   }
   public void myBusinessMethod() {
      // do stuff using dao
   }
}
注意属性设置器,在bean定义文档中,它对应与XML引用。这些将在对象使用之前被Spring调用.
这些应用bean不需要依赖于Spring。他们不需要实现任何Spring接口或者继承Spring的类:他们只需要遵守JavaBeans命名习惯。在Spring 应用环境之外重用它们是非常简单的,例如,一个测试环境。只是例示它有默认的构造器,并且通过setDataSource()和setExampleParam()的调用来手工设置它的属性。只要你有一个没有参数的构造器,如果你想在单行代码支持程序化的创建,你可以自由定义其他的带有多个属性构建的器。
注意,在业务接口中没有声明的JavaBean属性将会一起工作。 他们是一个实现细节。我们可以插入带有不同bean属性的不同的实现类而不影响连接对象或者调用代码。
当然,Spring XML bean factories 有更多的功能没有在这里描述,但是,这将给你一种基本使用的感觉。同时,简单的属性和有JavaBean属性编辑器的属性,Spring可以自动处理lists,maps和java.util.Properties.
 
阅读更多
换一批

没有更多推荐了,返回首页