注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

庄庄的家

庄庄的家-网易博客

 
 
 

日志

 
 

spring 控制反转容器 IOC 实例  

2008-03-18 22:15:36|  分类: java试题 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

3.3.1.3. spring 控制反转容器 IOC 实例

首先是一个用XML格式定义的Setter DI例子。相关的XML配置如下:

<bean id="exampleBean"   <!-- setter injection using the nested <ref/> element -->  <property name="beanOne"><ref bean="anotherExampleBean"/></property>  <!-- setter injection using the neater 'ref' attribute -->  <property name="beanTwo" ref="yetAnotherBean"/>  <property name="integerProperty" value="1"/></bean><bean id="anotherExampleBean"  id="yetAnotherBean"  <public class ExampleBean {    private AnotherBean beanOne;    private YetAnotherBean beanTwo;    private int i;    public void setBeanOne(AnotherBean beanOne) {        this.beanOne = beanOne;    }    public void setBeanTwo(YetAnotherBean beanTwo) {        this.beanTwo = beanTwo;    }    public void setIntegerProperty(int i) {        this.i = i;    }    }

正如你所看到的,bean类中的setter方法与xml文件中配置的属性是一一对应的。

接着是构造器注入的例子。以下是xml配置代码以及相对应的java类代码。

<bean id="exampleBean"     <!-- constructor injection using the nested <ref/> element -->  <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg>    <!-- constructor injection using the neater 'ref' attribute -->  <constructor-arg ref="yetAnotherBean"/>    <constructor-arg type="int" value="1"/></bean>  <bean id="anotherExampleBean"  id="yetAnotherBean"  <public class ExampleBean {      private AnotherBean beanOne;    private YetAnotherBean beanTwo;    private int i;        public ExampleBean(        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {        this.beanOne = anotherBean;        this.beanTwo = yetAnotherBean;        this.i = i;    }}

如你所见,在xml bean定义中指定的构造器参数将被用来作为传递给类ExampleBean构造器的参数。

现在来研究一个替代构造器的方法,采用静态工厂方法返回对象实例:

<bean id="exampleBean"       factory-method="createInstance">  <constructor-arg ref="anotherExampleBean"/>  <constructor-arg ref="yetAnotherBean"/>  <constructor-arg value="1"/> </bean><bean id="anotherExampleBean"  id="yetAnotherBean"  <public class ExampleBean {      // a private constructor    private ExampleBean(...) {      ...    }        // a static factory method; the arguments to this method can be    // considered the dependencies of the bean that is returned,    // regardless of how those arguments are actually used.    public static ExampleBean createInstance (            AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {        ExampleBean eb = new ExampleBean (...);        // some other operations        ...        return eb;    }}

请注意,传给静态工厂方法的参数由constructor-arg元素提供,这与使用构造器注入时完全一样。而且,重要的是,工厂方法所返回的实例的类型并不一定要与包含static工厂方法的类类型一致。尽管在此例子中它的确是这样。非静态的实例工厂方法与此相同(除了使用factory-bean属性替代class属性外),因而不在此细述。

3.3.2. 构造器参数的解析

构造器参数将根据类型来进行匹配。如果bean定义中的构造器参数类型明确,那么bean定义中的参数顺序就是对应构造器参数的顺序。考虑以下的类...

package x.y;  public class Foo {      public Foo(Bar bar, Baz baz) {        // ...    }}

这里的参数类型非常明确(当然前提是假定类BarBaz在继承层次上并无任何关系)。因此下面的配置将会很好地工作,且无须显式地指定构造器参数索引及其类型。

<beans>    <bean name="foo"         <constructor-arg>            <bean         </constructor-arg>        <constructor-arg>            <bean         </constructor-arg>    </bean></beans>

当引用的bean类型已知,则匹配没有问题(如上述的例子)。但是当使用象<value>true<value>这样的简单类型时,Spring将无法决定该值的类型,因而仅仅根据类型是无法进行匹配的。考虑以下将在下面两节使用的类:

package examples;  public class ExampleBean {      // No. of years to the calculate the Ultimate Answer    private int years;        // The Answer to Life, the Universe, and Everything    private String ultimateAnswer;      public ExampleBean(int years, String ultimateAnswer) {        this.years = years;        this.ultimateAnswer = ultimateAnswer;    }}

3.3.2.1. 构造器参数类型匹配

针对上面的这种情况,我们可以在构造器参数定义中使用type属性来显式的指定参数所对应的简单类型。例如:

<bean id="exampleBean"   <constructor-arg type="int" value="7500000"/>  <constructor-arg type="java.lang.String" value="42"/></bean>

3.3.2.2. 构造器参数的索引

通过使用index属性可以显式的指定构造器参数出现顺序。例如:

<bean id="exampleBean"   <constructor-arg index="0" value="7500000"/>  <constructor-arg index="1" value="42"/></bean>

使用index属性除了可以解决多个简单类型构造参数造成的模棱两可的问题之外,还可以用来解决两个构造参数类型相同造成的麻烦。注意:index属性值从0开始

[Tip] Tip

指定构造器参数索引是使用构造器IoC首选的方式。

3.3.3. bean属性及构造器参数详解

正如前面所提到的,bean的属性及构造器参数既可以引用容器中的其他bean,也可以是内联(inline,在spring的XML配置中使用<property/><constructor-arg/>元素定义)bean。

3.3.3.1. 直接量(基本类型、Strings类型等。)

<value/>元素通过字符串来指定属性或构造器参数的值。正如前面所提到的,JavaBean PropertyEditor将用于把字符串从java.lang.String类型转化为实际的属性或参数类型。

<bean id="myDataSource" destroy-method="close"      <!-- results in a setDriverClassName(String) call -->  <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>
3.3.3.1.1. idref元素

idref元素用来将容器内其它bean的id传给<constructor-arg/><property/>元素,同时提供错误验证功能。

<bean id="theTargetBean"   <bean id="theClientBean"     <property name="targetName">        <idref bean="theTargetBean" />    </property></bean>

上述bean定义片段完全地等同于(在运行时)以下的片段:

<bean id="theTargetBean"   <bean id="client"     <property name="targetName">        <value>theTargetBean</value>    </property></bean>

第一种形式比第二种更可取的主要原因是,使用idref标记允许容器在部署时 验证所被引用的bean是否存在。而第二种方式中,传给client bean的targetName属性值并没有被验证。任何的输入错误仅在client bean实际实例化时才会被发现(可能伴随着致命的错误)。如果client bean 是prototype类型的bean,则此输入错误(及由此导致的异常)可能在容器部署很久以后才会被发现。

此外,如果被引用的bean在同一XML文件内,且bean名字就是bean id,那么可以使用local属性,此属性允许XML解析器在解析XML文件时来对引用的bean进行验证。

<property name="targetName">   <!-- a bean with an id of 'theTargetBean' must exist, else an XML exception will be thrown -->   <idref local="theTargetBean"/></property>

上面的例子与在ProxyFactoryBean bean定义中使用<idref/>元素指定AOP interceptor的相同之处在于:如果使用<idref/>元素指定拦截器名字,可以避免因一时疏忽导致的拦截器ID拼写错误。

  评论这张
 
阅读(359)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017