包办婚姻的Spring IoC

转自:http://blog.csdn.net/xiaoxian8023/article/details/17148931

基本概念

       IoC(Inversion of Control),直观地讲,就是对象创建或查找对象依赖的控制权由应用代码转到了外部容器,控制权的转移是所谓反转。使用Ioc,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。我们可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它


       IoC还有另外一个名字——“依赖注入DI(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,形象地说,即由容器动态地将某种依赖关系注入到组件之中。


IoC场景

      上面说的可能有点晕,来一个实际点的例子。


      丽萨已经老大不小了,一直没有男朋友,看着别人恩恩爱爱的,也不禁想找个BoyFriend。摆在她面前的有3种方案:主动“邂逅” Or 同事介绍 Or 父母包办。她会选择哪种呢?

      主动“邂逅”方式,如图所示:


  1. public class Girl {   
  2.   
  3.   public void kiss(){   
  4.     Boy boy = new Boy();   
  5.   }   
  6.   
  7. }   
       不过这种美好的纯洁的爱情,一般只会发生在校园里,对于已经是工薪阶层的丽萨显然不太适合。

      第二方案,同事介绍,

  1. public class Girl {   
  2.   
  3.   void kiss(){   
  4.     Boy boy = BoyFactory.createBoy();   
  5.   }   
  6. }   

       很多人都是这样找到了自己的另一半。丽萨以前也试着去跟同事介绍的handsome man接触过,但是真人与介绍的出入太大,最起码handsome这条就不太符合,而且有他许多缺点。觉得他不适合自己,所以最后也就不了了之。


       所以无奈之下,她的难题丢给了父母。父母给她物色了一个“绝世好男人”——曾小贤(这娃有句经典台词:“好男人就是我,我就是....曾小贤”),终于算是遂了她的心愿了。

  1. public class Girl {   
  2.   
  3.   void kiss(Boy boy){   
  4.     // kiss boy   
  5.    boy.kiss();   
  6.   }   
  7. }   

       虽然在现实生活中我们都希望与自己的另一半来场完美的邂逅,但在spring世界里,跟丽萨一样,选择的却是父母包办,它就是控制反转,而这里具有控制力的父母,就是Spring所谓的容器概念。 


       典型的IoC可以如图所示。

 实例说明IoC注入方式

      IoC有3种注入方式:接口注入、Setter方法注入、构造器注入。由于接口注入不推荐使用,所以只介绍setter方法注入和构造器注入。


       用代码来说明一切吧:

【Girl.Java

  1. package com.tgb;  
  2. /** 
  3.  * 期待找BF的Girl 
  4.  * @author Admin 
  5.  * 
  6.  */  
  7. public class Girl {  
  8.   
  9.     private Boy bf;  
  10.       
  11.       
  12.     public Girl(){}  
  13.       
  14.     public Girl(Boy bf){  
  15.         System.out.print("使用构造方法方式注入:");  
  16.         this.bf = bf;  
  17.     }  
  18.       
  19.     public void setBf(Boy bf) {  
  20.         System.out.print("使用Setter方式注入:");  
  21.         this.bf = bf;  
  22.     }  
  23.   
  24.     public void kissYourBF() {  
  25.         bf.kiss();  
  26.     }  
  27. }  
【Boy.java】
  1. package com.tgb;  
  2.   
  3. /** 
  4.  * 合格的BF 
  5.  * @author Admin 
  6.  * 
  7.  */  
  8. public class Boy {  
  9.   
  10.     public void kiss(){  
  11.         System.out.println("My boy friend,I'll kiss you!");  
  12.     }  
  13. }  
【Client客户端】
  1. package com.tgb;  
  2.   
  3. import org.springframework.context.ApplicationContext;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. public class Client {  
  7.   
  8.     public static void main(String[] agrs){  
  9.         ApplicationContext factory =  ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");    
  10.           
  11.         Girl lisa = (Girl)factory.getBean("girl");  
  12.         lisa.kissYourBF();  
  13.           
  14.     }  
  15. }  

【applicationContext.xml配置文件】

注意:因为路径配置的是 ClassPathXmlApplicationContext("applicationContext.xml");所以applicationContext.xml一定要放在src路径下,不要放在他的二级目录

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xmlns:aop="http://www.springframework.org/schema/aop"  
  5.          xmlns:tx="http://www.springframework.org/schema/tx"  
  6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  9.   
  10.     <bean id="boy" class="com.tgb.Boy" />  
  11.     <bean id="girl" class="com.tgb.Girl">  
  12.         <!--构造器注入-->  
  13.         <constructor-arg ref="boy"></constructor-arg>  
  14.         <!--Setter方法注入-->  
  15.         <!--<property name="bf" ref="boy"></property>-->  
  16.     </bean>  
  17. </beans>  

       选择Setter方法注入和 构造器注入的控制是在配置文件中完成的。结果如下:




      Setter方法注入时,有2种装载方式需要注意,byName和byType。当我在配置文件中,把2种注入方式都注释掉,同时添加了default-autowire="byType",

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.          xmlns:aop="http://www.springframework.org/schema/aop"  
  5.          xmlns:tx="http://www.springframework.org/schema/tx"  
  6.          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  7.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
  8.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"  
  9.            default-autowire="byType"  
  10.            >  
  11.   
  12.     <bean id="boy" class="com.tgb.Boy" />  
  13.     <bean id="girl" class="com.tgb.Girl">  
  14.         <!--构造器注入-->  
  15.         <!--<constructor-arg ref="boy"></constructor-arg>-->  
  16.         <!--Setter方法注入-->  
  17.         <!--<property name="bf" ref="boy"></property>-->  
  18.     </bean>  
  19. </beans>  

       执行结果如图



       但是换成default-autowire="byName",则会报如下错误:


       这是为什么呢?原因在于,当使用byType方式装载时,Spring是根据classType来确定要实例化的类。所以就算bean的id是boy,跟Girl中bf的Setter名字不一致,依旧可以实例化。但是使用byName时,则是根据id来实例化类的。所以只要把Boy类对应的bean id跟Girl中的setter方法名一致才行,即修改id="boy"为id="bf",即可正常显示:

  1. <bean id="bf" class="com.tgb.Boy" />  
  2. <bean id="girl" class="com.tgb.Girl">  
  3.     <!--构造器注入-->  
  4.     <!--<constructor-arg ref="boy"></constructor-arg>-->  
  5.     <!--Setter方法注入-->  
  6.     <!--<property name="bf" ref="boy"></property>-->  
  7. </bean>  

       另一种修改方式就是用显示的方式来设定Setter方法所注入的是哪个类的对象:

  1. <bean id="boy" class="com.tgb.Boy" />  
  2. <bean id="girl" class="com.tgb.Girl">  
  3.     <!--构造器注入-->  
  4.     <!--<constructor-arg ref="boy"></constructor-arg>-->  
  5.     <!--Setter方法注入-->  
  6.     <property name="bf" ref="boy"></property>  
  7. </bean>  
       执行结果如图:


2种注入方式的比较

       Setter 注入:

    • 对于习惯了传统 javabean 开发的程序员,通过 setter 方法设定依赖关系更加直观。
    • 如果依赖关系较为复杂,那么构造子注入模式的构造函数也会相当庞大,而此时设值注入模式则更为简洁。
    • 如果用到了第三方类库,可能要求我们的组件提供一个默认的构造函数,此时构造子注入模式也不适用。

       构造器注入:

    • 在构造期间完成一个完整的、合法的对象。
    • 所有依赖关系在构造函数中集中呈现。
    • 依赖关系在构造时由容器一次性设定,组件被创建之后一直处于相对“不变”的稳定状态。
    • 只有组件的创建者关心其内部依赖关系,对调用者而言,该依赖关系处于“黑盒”之中。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值