现在的位置: 首页 > 综合 > 正文

Spring–多种Bean的注入(中)

2013年02月13日 ⁄ 综合 ⁄ 共 3187字 ⁄ 字号 评论关闭

今天办理交接手续,没有安排任务,继续整理剩下的多种Bean注入的文章,如果还有时间谈谈我理解的IoC原理方面的东东和Bean的生命周期,一步步打通任督二脉。

正如上篇所讲,Spring是支持各种对象依赖注入的,注入的方式也灵活多变,下面以Setter为主,讲解我所了解的一些类型的注入:

1.基本类型

先看下面的配置,Java部分省略(例子全部来源于网络):

 <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" init-method="init" destroy-method="close">

          <property name="username">

               <value>root</value>

          </property>

          <property name="password">

               <value>masterkaoli</value>

          </property>

    </bean>

   从配置来看,总共注入了两个String类型的变量值,usernamepassword,如果注入的是integer或别的类型,触类旁通。重点了解init-methoddestroy-method两个属性,前者可配置一个初始化方法,用来完成构造器以后执行的方法,一些需要类中需要初始化的事情可以都交给他来做;destroy-method这个方法一般是在容器销毁的时候调用,采用此种配置,Spring容器将使用JavaBeanPropertyEditor<value/>元素中的字符转换为实际属性或参数类型,Spring团队较倾向于此种方式。

为尽可能全面些,提供另一种配置方式:

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" init-method="init" destroy-method="close">

  <property name="username" value="root"/>

  <property name="password" value="masterkaoli"/>

</bean>

除了<property><constructor-arg/>也支持“value”属性,这样会使配置比较简单,本人较喜欢这种配置方式。

再看一个例子:

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">

    <property name="targetName">

       <idref bean="theTargetBean" />

    </property>

</bean>

这个配置等同于下面的配置:

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">

    <property name="targetName" value="theTargetBean" />

</bean>

上面的配置中没有出现<idref/>这个元素,细心的读者可能已经发现了,<idref/>其实就是“value”,不同是什么呢?<idref/>value多了一个验证功能,他会在容器部署的时候去验证是否真的存在一个叫“theTargetBean”Bean,如果没有则会抛出异常,如此就能降低后期错误的几率,因此,推荐使用<idref/>,它与<ref/>的区别后面我会讲到。

2.引用其他Bean

引用外部的Bean一般靠<ref/>元素,举例说明:

<bean name="/errorHandleConfigAction" class="com.action.ErrorHandleConfigAction">

    <property name="errorStrategyService">

         <ref bean="errorStrategyService"/>

     </property>

 </bean>

这种形式是较为常见的形式,通过<ref/>标签的bean属性来指定目标BeanerrorStrategyService,此种配置方式会引用同一容器中内的任何Bean,无论是否是在同一xml中。到这里你可能也就明白了<ref/><idref/>的本质区别了:前者引用的是bean的一个实例对象,而后者引用的仅仅是beanidname,这两个标签的区别不是一般的大,是不能搞混的。

再看一个例子:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

     <property name="sessionFactory">

         <ref local=" sessionFactory"/>

     </property>

</bean>

这种形式是通过<ref/>标签的local属性指定目标bean,他利用XML解析器来验证引用bean是否在同一文件中,如果在同一xml中没有找到,则会抛出异常,local属性值必须是目标beanid属性值,在同一个文件中,推荐使用local

上面两个例子中,我在第一个bean的定义中用了name,而第二个用了id,他俩有什么区别呢?首先说,idname同样都是指定bean的名称,但使用场景有别;idbean的唯一标识,不能重复,XML解析器会根据DTD来验证被引用的有效性,但这也带来了id命名规则方面的限制,不能以数字符合打头,不能出现空格,因此,在SpringStruts整合中要格外注意了。

基于这个缺陷,name应运而生,他支持重名,一般是后面的覆盖前面的,支持一bean多名,中间可用逗号分隔,如:<beanname="b1,b2,b3">;一般如果id属性不存在,则name中的第一个充当id。所以,一般情况下,推荐使用id属性!

还有一种形式的引用是,通过<ref/>标签中的parent属性引用当前容器中父容器的bean,对此不甚了解,感兴趣的可以百度下。

3.内联和外联

本想一气呵成,可内容貌似有点多,分成上中下三篇吧,这篇结尾说说项目中常见的两种配置风格。根据应用场景,把bean之间的依赖注入的配置划分成内联和外联,我自己这么叫,不知准确否?外联就是我上面第2条这种形式;那何为内联呢,也叫内部bean,举例说明:

<bean id="outer" class="...">

  <!-- instead of using a referenceto a target bean, simply define the target bean inline -->

  <propertyname="target">

    <bean class="com.example.Person"> <!-- this is the inner bean -->

      <property name="name" value="Fiona Apple"/>

      <property name="age" value="25"/>

    </bean>

  </property>

</bean>

从上面的例子看出,outer依赖target这个bean,但他并没有采用我们在第2条引用其他bean所说的那样,采用<ref/>标签去处理,而是直接使用<bean/>标签指向了实际的目标bean,内部bean总是匿名并且他们总是prototype模式,同时将内部bean注入到包含该内部bean之外的bean是不可能的,内部bean定义不需要指定idname属性,即使指定也会被容器所忽略,虽然这样让配置清爽了不少,但也是缺陷,就是不能复用。在没有复用的情况下推荐使用内联;而需要复用时,推荐使用外联(上面第2条已经讲过了,不再举例)。

抱歉!评论已关闭.