zoukankan      html  css  js  c++  java
  • Spring学习笔记(6)——IoC的三种注入方式

    1. 1.接口注入(不推荐
    2. 2.构造器注入(死的应用
    3. 3.getter,setter方式注入(比较常用

    Type1 接口注入

    我们常常借助接口来将调用者与实现者分离。如:

    1. public class ClassA {  
    2.   private InterfaceB clzB;  
    3.   public init() {  
    4.   Ojbect obj =  
    5.   Class.forName(Config.BImplementation).newInstance();  
    6.   clzB = (InterfaceB)obj;  
    7.   }  
    8.   ……  
    9.   }  

      上面的代码中,ClassA依赖于InterfaceB的实现,如何获得InterfaceB实现类的实例?传统的方法是在代码中创建InterfaceB实现类的实例,并将起赋予clzB。

      而这样一来,ClassA在编译期即依赖于InterfaceB的实现。为了将调用者与实现者在编译期分离,于是有了上面的代码,我们根据预先在配置文件中设定的实现类的类名,动态加载实现类,并通过InterfaceB强制转型后为ClassA所用。
      这就是接口注入的一个最原始的雏形。
      而对于一个Type1型IOC容器而言,加载接口实现并创建其实例的工作由容器完成,如J2EE开发中常用的Context.lookup(ServletContext.getXXX),都是Type1型IOC的表现形式。
      Apache Avalon是一个典型的Type1型IOC容器。

    Type2 构造子注入

    构造子注入,即通过构造函数完成依赖关系的设定,如:

    1. public class DIByConstructor {  
    2.   private final DataSource dataSource;  
    3.   private final String message;  
    4.   public DIByConstructor(DataSource ds, String msg) {  
    5.   this.dataSource = ds;  
    6.   this.message = msg;  
    7.   }  
    8.   ……  
    9.   }  

      可以看到,在Type2类型的依赖注入机制中,依赖关系是通过类构造函数建立,容器通过调用类的构造方法,将其所需的依赖关系注入其中。
      PicoContainer(另一种实现了依赖注入模式的轻量级容器)首先实现了Type2类型的依赖注入模式。

    Type3 设值注入

      在各种类型的依赖注入模式中,设值注入模式在实际开发中得到了最广泛的应用(其中很大一部分得力于Spring框架的影响)。
      在笔者看来,基于设置模式的依赖注入机制更加直观、也更加自然。Quick Start中的示例,就是典型的设置注入,即通过类的setter方法完成依赖关系的设置。

    几种依赖注入模式的对比总结

      接口注入模式因为具备侵入性,它要求组件必须与特定的接口相关联,因此并不被看好,实际使用有限。
      Type2和Type3的依赖注入实现模式均具备无侵入性的特点。在笔者看来,这两种实现方式各有特点,也各具优势(一句经典废话?)。

    Type2 构造子注入的优势:

    1. “在构造期即创建一个完整、合法的对象”,对于这条Java设计原则,Type2无疑是最好的响应者。
    2. 避免了繁琐的setter方法的编写,所有依赖关系均在构造函数中设定,依赖关系集中呈现,更加易读。
    3. 由于没有setter方法,依赖关系在构造时由容器一次性设定,因此组件在被创建之后即处相对“不变”的稳定状态,无需担心上层代码在调用过程中执行setter方法对组件依赖关系产生破坏,特别是对于Singleton模式的组件而言,这可能对整个系统产生重大的影响。
    4. 同样,由于关联关系仅在构造函数中表达,只有组件创建者需要关心组件内部的依赖关系。对调用者而言,组件中的依赖关系处于黑盒之中。对上层屏蔽不必要的信息,也为系统的层次清晰性提供了保证。
    5. 通过构造子注入,意味着我们可以在构造函数中决定依赖关系的注入顺序,对于一个大量依赖外部服务的组件而言,依赖关系的获得顺序可能非常重要,比如某个依赖关系注入的先决条件是组件的DataSource及相关资源已经被设定。

    Type3 设值注入的优势:

    1. 对于习惯了传统JavaBean开发的程序员而言,通过setter方法设定依赖关系显得更加直观,更加自然。
    2. 如果依赖关系(或继承关系)较为复杂,那么Type2模式的构造函数也会相当庞大(我们需要在构造函数中设定所有依赖关系),此时Type3模式往往更为简洁。
    3. 对于某些第三方类库而言,可能要求我们的组件必须提供一个默认的构造函数(如Struts中的Action),此时Type2类型的依赖注入机制就体现出其局限性,难以完成我们期望的功能。

      可见,Type2和Type3模式各有千秋,而Spring、PicoContainer都对Type2和Type3类型的依赖注入机制提供了良好支持。这也就为我们提供了更多的选择余地。理论上,以Type2类型为主,辅之以Type3类型机制作为补充,可以达到最好的依赖注入效果,不过对于基于Spring Framework开发的应用而言,Type3使用更加广泛。借鉴http://blog.csdn.net/zhuangzhineng/article/details/3967234

    一、构造器注入

         构造器注入顾名思义就是在程序组件中实现构造器,构造器可以是一个也可以是多个。废话不多说,直接上代码。

    Java代码 复制代码 收藏代码
    1. package cn.glzaction.service.impl;  
    2.   
    3. import java.util.List;  
    4.   
    5. import cn.glzaction.service.interfaces.PersonDaoIF;  
    6. import cn.glzaction.service.interfaces.PersonServiceIF;  
    7.   
    8. public class PersonServiceBean implements PersonServiceIF{  
    9.   
    10. //自定义类  
    11.     private PersonDaoIF personDaoBean;  
    12. //String类型  
    13.     private String name;  
    14. //集合类型    
    15.     private List list;  
    16.       
    17. //构造器     
    18.     public PersonServiceBean(PersonDaoBean personDaoBean,String name,List list){  
    19.         this.personDaoBean = personDaoBean;  
    20.         this.name = name;  
    21.         this.list = list;  
    22.     }  
    23. //方法,用于显示  
    24.     public void display(){  
    25.         personDaoBean.add();  
    26.         System.out.println(name);  
    27.         System.out.println(list);  
    28.     }  
    29. }  

    上面的代码中构造器要注入三个参数,同时这三个参数也是三种不同的类型,自定义类、String类型,集合类型,其中自定义类PersonDaoBean 具体的实现我们这里就不累述了,因为这不是重点。下面我们再来看一下在Spring的配置文件中如何来配置。

    Xml代码 复制代码 收藏代码
    1. <bean id="personDao" class="cn.glzaction.service.impl.PersonDaoBean"></bean >  
    2.   
    3. <!--构造器方式注入-->  
    4. <bean id="personService" class="cn.glzaction.service.impl.PersonServiceBean">  
    5.     <constructor-arg index="0" type="cn.glzaction.service.impl.PersonDaoBean" ref="personDao"/>  
    6.     <constructor-arg index="1" type="java.lang.String" value="glzaction"/>  
    7.     <constructor-arg index="2" type="java.util.List">  
    8.         <list>  
    9.             <value>list1</value>  
    10.             <value>list2</value>  
    11.             <value>list3</value>  
    12.         </list>  
    13.     </constructor-arg>  
    14. </bean>  

          java代码如何实现构造器我想大家一定都很清楚,否则的话就有点讲不过去了,呵呵,所以这里我也就不加以说明了,主要说一下上面的xml配置。id为“personDao”的bean是PersonServiceBean的私有属性,它的注入是采用无参构造器的注入方式注入的,这也不详细说明。主要说一下id为“personService”类的构造器注入。<coustructor-arg>是构造器标签元素,通过设定它的属性可以往构造器传递参数,index属性值表示要设定的参数在构造器形参中的索引顺序,例如上面的配置,list是第三个参数,所以它对应的索引为2,index是可选属性,所谓可选并不是说在任何情况下都可以不使用,要视具体情况而定,type为参数的类型,这个也是可选参数。还有两个很重要的属性就是ref和value,如果注入的是bean,就要使用ref,ref的值就是对应的bean。如果注入的是基本类型或者string类型就用value,直接将对应的值填入即可。

     

    二、设值注入(setter方式注入)

    设值注入就是通过setXxxx方法将bean注入到组件中,自定义类如下

    Java代码 复制代码 收藏代码
    1. package cn.glzaction.service.impl;  
    2.   
    3. import cn.glzaction.service.interfaces.PersonDaoIF;  
    4. import java.util.*;  
    5.   
    6. public class PersonDaoBean implements PersonDaoIF {  
    7.   
    8.     private String name;  
    9.       
    10.     private Integer id;  
    11.       
    12.     private List list;  
    13.       
    14.     private Map map;  
    15.       
    16.     public void setName(String name) {  
    17.         this.name = name;  
    18.     }  
    19.     public void setId(Integer id) {  
    20.         this.id = id;  
    21.     }  
    22.     public void setList(List list) {  
    23.         this.list = list;  
    24.     }  
    25.     public void setMap(Map map) {  
    26.         this.map = map;  
    27.     }  
    28.   
    29.     @Override  
    30.     public void add() {  
    31.         // TODO Auto-generated method stub  
    32.         System.out.println(map);  
    33.         System.out.println(list);  
    34.         System.out.println(id);  
    35.         System.out.println(name);  
    36.     }  
    37. }  

    采用设置注入只要有setter方法即可,但是有时由于编程习惯也会讲getter方法引进,但是要清楚:设值注入与getter方法无关。这里还有一点需要注意,那就是能使用基本类型,如果非要使用基本类型的话就要使用其对应的包装类型,如上面使用的是Integer而不是int。Spring的xml配置如下: 

    Xml代码 复制代码 收藏代码
    1. <bean id="personDao" class="cn.glzaction.service.impl.PersonDaoBean">  
    2.     <property name="name" type="java.lang.String" value="glzaction"/>  
    3.     <property name="id" type="java.lang.Integer" value="1"/>  
    4.     <property name="list" type="java.util.List">  
    5.         <list>  
    6.             <value>list1</value>  
    7.             <value>list2</value>  
    8.             <value>list3</value>  
    9.         </list>  
    10.     </property>  
    11.     <property name="map" type="java.util.Map">  
    12.         <map>  
    13.             <entry key="key1" value="value1"></entry>  
    14.             <entry key="key2" value="value2"></entry>  
    15.         </map>  
    16.     </property>  
    17. </bean>  

     

    设值注入采用的是<property>标签元素,其中的name属性对应的是要注入的变量名,type属性值对应的该变量的类型,可以是自定义类或者包装类型。value属性对应的是相应的值,还有一个ref属性,该属性值对应的是bean。

    http://blog.csdn.net/u011225629/article/details/45437503

  • 相关阅读:
    布隆过滤器解决缓存穿透问题
    查询指定距离内的快递柜或者店铺
    各注册中心consul eureka 以及nacos的服务发现原理
    consul注册中心服务注册过程源码分析
    consul注册中心如何自动剔除下线服务
    svn执行reflash/cleanup报错wc.db解决办法
    第二章
    第一章 JVM和Java体系架构
    2、操作系统-中断
    1、操作系统-启动
  • 原文地址:https://www.cnblogs.com/itommy/p/10610471.html
Copyright © 2011-2022 走看看