文档章节

Spring学习笔记(6)---------IoC的三种注入方式

Simon丶Ma
 Simon丶Ma
发布于 2016/04/14 14:57
字数 2484
阅读 16
收藏 0
  1. 接口注入(不推荐
  2. 构造器注入(死的应用
  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. }  
<span style="font-size:18px;">package cn.glzaction.service.impl;

import java.util.List;

import cn.glzaction.service.interfaces.PersonDaoIF;
import cn.glzaction.service.interfaces.PersonServiceIF;

public class PersonServiceBean implements PersonServiceIF{

//自定义类
	private PersonDaoIF personDaoBean;
//String类型
	private String name;
//集合类型	
	private List list;
	
//构造器	
	public PersonServiceBean(PersonDaoBean personDaoBean,String name,List list){
		this.personDaoBean = personDaoBean;
		this.name = name;
		this.list = list;
	}
//方法,用于显示
	public void display(){
		personDaoBean.add();
		System.out.println(name);
		System.out.println(list);
	}
}</span>

 

 

 

上面的代码中构造器要注入三个参数,同时这三个参数也是三种不同的类型,自定义类、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>  
<span style="font-size:18px;"><bean id="personDao" class="cn.glzaction.service.impl.PersonDaoBean"></bean >

<!--构造器方式注入-->
<bean id="personService" class="cn.glzaction.service.impl.PersonServiceBean">
	<constructor-arg index="0" type="cn.glzaction.service.impl.PersonDaoBean" ref="personDao"/>
	<constructor-arg index="1" type="java.lang.String" value="glzaction"/>
	<constructor-arg index="2" type="java.util.List">
		<list>
			<value>list1</value>
			<value>list2</value>
			<value>list3</value>
		</list>
	</constructor-arg>
</bean></span>

 

 

      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. }  
<span style="font-size:18px;">package cn.glzaction.service.impl;

import cn.glzaction.service.interfaces.PersonDaoIF;
import java.util.*;

public class PersonDaoBean implements PersonDaoIF {

	private String name;
	
	private Integer id;
	
	private List list;
	
	private Map map;
	
	public void setName(String name) {
		this.name = name;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public void setList(List list) {
		this.list = list;
	}
	public void setMap(Map map) {
		this.map = map;
	}

	@Override
	public void add() {
		// TODO Auto-generated method stub
		System.out.println(map);
		System.out.println(list);
		System.out.println(id);
		System.out.println(name);
	}
}</span>

 

 

 

采用设置注入只要有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>  
<span style="font-size:18px;"><bean id="personDao" class="cn.glzaction.service.impl.PersonDaoBean">
	<property name="name" type="java.lang.String" value="glzaction"/>
	<property name="id" type="java.lang.Integer" value="1"/>
	<property name="list" type="java.util.List">
		<list>
			<value>list1</value>
			<value>list2</value>
			<value>list3</value>
		</list>
	</property>
	<property name="map" type="java.util.Map">
		<map>
			<entry key="key1" value="value1"></entry>
			<entry key="key2" value="value2"></entry>
		</map>
	</property>
</bean></span>

 

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

 

 

 

 

© 著作权归作者所有

共有 人打赏支持
Simon丶Ma
粉丝 4
博文 134
码字总数 299850
作品 0
深圳
程序员
私信 提问
【Spring学习笔记】--IOC学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/YYZZHC999/article/details/82824751 spring ioc原理 Ioc—Inversion of Control,即“控制反转”,不是什么技...

Hepburn_Yang
09/23
0
0
IOC/AOP工具 - jBeanBox

jBeanBox是一个微形但功能较齐全的IOC/AOP工具适用于JAVA7+,利用了Java的初始化块实现的Java配置代替XML。jBeanBox采用Apache License 2.0开源协议。 其他一些IOC/AOP框架的问题: 1)Sprin...

yong9981
2016/07/25
0
14
Spring框架笔记(三)——Spring容器、属性注入和构造器注入详解

Spring 容器 在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用. Spring 提供了两种类型的 IOC 容器...

HappyBKs
2015/07/12
0
5
Java笔记——看完这个,打通Spring难度系数

写在前面经过一段时间的整理,希望读者看完后对自己的知识点有所帮助。 写过java的都知道:所有的对象都必须创建;或者说:使用对象之前必须先创建。而使用ioc之后,你就可以不再手动创建对象...

简祥
09/14
0
0
【死磕 Spring】----- IOC 之深入理解 Spring IoC

版权声明:版权声明:转载前请留言获得作者许可,转载后标明作者 chenssy 和原文出处。原创不易,感谢您的支持 https://blog.csdn.net/chenssy/article/details/82343456 在一开始学习 Spri...

chenssy
09/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

小白带你认识netty(三)之NioEventLoop的线程(或者reactor线程)启动(一)

在第一章中,我们看关于NioEventLoopGroup的初始化,我们知道了NioEventLoopGroup对象中有一组EventLoop数组,并且数组中的每个EventLoop对象都对应一个线程FastThreadLocalThread,那么这个...

天空小小
今天
3
0
PHP动态扩展Redis模块

查看已有模块 [root@test-a ~]# /usr/local/php/bin/php -m[PHP Modules]bz2Core...zlib[Zend Modules] 下载包,解压,生成configure文件 [root@test-a ~]# cd /usr/local/src/[ro......

野雪球
今天
3
0
在Ignite中使用线性回归算法

在本系列前面的文章中,简单介绍了一下Ignite的机器学习网格,下面会趁热打铁,结合一些示例,深入介绍Ignite支持的一些机器学习算法。 如果要找合适的数据集,会发现可用的有很多,但是对于...

李玉珏
今天
5
0
Mybatis应用学习——简单使用示例

1. 传统JDBC程序中存在的问题 1. 一个简单的JDBC程序示例: public class JDBCDemo {public static void main(String[] args) {Connection con=null;PreparedStatement statemen...

江左煤郎
今天
4
0
使用JavaScript编写iOS应用业务逻辑

JSAUIKitCocoa使你可以使用JavaScript编写对性能要求不高但可能变动性很大的iOS应用的业务逻辑部分,View组件、需要多线程支持的Model等则直接使用原生对象。 编写方式与React Native相似,但...

neal01
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部