spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转(依赖注入)进行简单的总结。

一、控制反转与依赖注入的概念

  在学习spring框架的时候,我们习惯性地将控制反转和依赖注入放在一起,其实,两者体现的思想原则都是差不多的,只不过控制反转是一种更广泛的程序操作理念,而依赖注入是一种更为具体的实现方法,总的来说,控制反转可以依靠依赖注入来实现。

  1、控制反转的概念。

    在设计模式的总结中,我也曾经在设计模式的博客中总结了控制反转类似的概念思想(可以参考本人这篇博客),它的核心方法理念其实就是通过接口编程,然后让调用者决定实际生产过程用什么类型的接口实现类。当然,在spring中,上面所说的具体类初始化、注入调用代码等过程都是由spring来完成的。上面文字可能稍微抽象化了点,下面上点代码简单说明这个过程,注意看注释:

//应用程序对应的类
public class IocBlog {
//这里定义接口,通过接口操作对象,从而达到多态的效果
UserIfc user = null;
/*spring会通过反射机制,利用setter注入(具体的操作方法是我们在spring配置文件中配置相应bean的property属性即可)
* 后面的login方法的调用时,就是根据这个注入的类是什么类型进行相应的方法调用的,我们可以针对不同的user实现了注入对应的
* 用户对象,而应用程序本身不用根据不同的用户种类进行改变,这便达到了代码解耦的目的。当然,注入的过程是由spring帮我们完成的,这个后面再具体讲
*/
public void setUser(UserIfc user) {
this.user = user;
}
//这是具体的调用方法
public void loginDo() {
//通过接口,引用具体的User对象
user.login();
}
} //先简单定义一个用户接口
interface UserIfc{
//简单的登录方法
public void login();
}
//一个具体实现类,该类是在运行时有spring动态地注入的
class User implements UserIfc{
public void login() {
System.out.println("user method login");
}
}

上面这段代码代替说明了控制反转的核心思想--就是通过接口操纵具体实现类,也体现了设计模式中一个很重要的原则:不用程序本身来找具体实现类,而是调用者来决定具体实现类是什么。

下面再具体说明,在spring中如何实现类注入的。 在进行具体的用法之前,有必要先理解依赖注入这个概念。 

  2、依赖注入概念。

  上面也提到,依赖注入是控制反转的一种具体实现手段,通过依赖注入方法可以达到控制反转的目的。其实依赖注入个人理解就是:通过反射机制在程序运行的时候动态地创建具体实现类的对象,然后在需要该对象的时候通过某种手段(一般是通过该bean对象的对应id)将该对象拿出来(也就是注入到具体需要用的地方)。当然,上面这些复制的过程包括类的创建、维护、注入等工作都是spring帮我们完成的。

理解了依赖注入和控制反转之后,废话不多说,下面具体看看在spring中如何具体地运用。

二、spring中如何注入对象。

  1、具体的注入方法

  接着上面的user类例子说明spring中对象注入的方法,先看下面改进之后的代码(加了个main方法表示具体的调用过程)

//应用程序对应的类
public class IocBlog {
//这里定义接口,通过接口操作对象,从而达到多态的效果
UserIfc user = null;
/*spring会通过反射机制,利用setter注入(具体的操作方法是我们在spring配置文件中配置相应bean的property属性即可)
* 后面的login方法的调用时,就是根据这个注入的类是什么类型进行相应的方法调用的,我们可以针对不同的user实现了注入对应的
* 用户对象,而应用程序本身不用根据不同的用户种类进行改变,这便达到了代码解耦的目的。当然,注入的过程是由spring帮我们完成的,这个后面再具体讲
*/
public void setUser(UserIfc user) {
this.user = user;
}
//这是具体的调用方法
public void loginDo() {
//通过接口,引用具体的User对象
user.login();
} //定义main方法表示具体的调用过程
public static void main(String [] args){
//加载配置文件上下文,该对象存储有类之间的依赖关系
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过上下文对象获取具体的bean对象,该对象具体类型在配置文件中指明
IocBlog test = (IocBlog)appContext.getBean("testId");//一般通过id获取
//通过loginDo调用login,不同的User类的注入对象会调用不同的对应login方法,他们之间的依赖关系通过配置文件指明
test.loginDo();
}
} //先简单定义一个用户接口
interface UserIfc{
//简单的登录方法
public void login();
}
//一个具体实现类,该类是在运行时有spring动态地注入的
class User implements UserIfc{
private String userName = null;//用户名
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
} public void login() {
System.out.println("user method login");
}
}

  然后,我们通过以下配置文件进行类注入操作,请注意看注释:

<!-- 这里声明了bean,意思是告诉spring:我有这样一个类,它在 review.blog.springRevice.User路径下
这个类需要你初始化,因为我在将来的某个时刻可能要用该类(具体初始化可以通过配置来决定顺序,这里不详细讲)
-->
<bean id="userId" class="review.blog.springRevice.User">
<!-- property是对应有setter方法的属性值,必须和name一致 -->
<property name="userName" value="UserName1"/>
</bean> <bean id="testId" class="review.blog.springRevice.IocBlog">
<!-- 通过ref引用userId,这时,sprign会帮我们将userId对应的对象注入到testId对应的对象的user属性中 -->
<property name="user" ref="userId"></property>
</bean>

  可以看到,通过spring,我们可以实现代码组件之间最大程度的松耦合,对象之间的依赖关系不会硬编码到代码中去,而是通过一个配置文件进行映射操作,这大大提高了代码的重用性以及可扩展性。

  2、spring中实现注入原理的简单总结

    总的来说,注入的实现方法还是反射。spring通过dom4j等组件将配置文件加载解析获得对应的类名字之后,利用class.forName方法加载对象。在bean维护中,spring是通过一个map进行对象的维护的,key对应的就是id值,value对应的是对象(从这里看出,spring中bean对象默认是单例的,当然,通过配置文件我们可以改变单例模式,这个不详细讲),具体就不粘贴源码了,有兴趣的可以自己看spring的源码。

  3、其他数据类型的配置使用方法

    在spring中,不仅仅支持普通对象,它也支持map和list等集合类,具体的配置方式也比较简单,下面简单上个demo供参考:

  Map配置方式

<!--map配置方式 -->
<bean id="test" class="Test">
<property name="testMap">
<map>
<entry key="a">
<value>1</value>
</entry>
<entry key="b">
<value>2</value>
</entry>
</map>
</property>
</bean>

  list配置方式

<!-- list配置方式 -->
<bean>
<property name="listTestString">
<list>
<value>这里可以是字符串</value>
<value>也可以不是字符串,具体看下面</value>
</list>
</property>
<property name="listTestRef">
<list>
<ref bean="beanId1"/>
<ref bean="beanId2"/>
</list>
</property>
</bean>

  当然,spring还支持很多其他方面的配置,具体就不一一讲解了,可以去官网看spring api

spring学习总结一----控制反转与依赖注入的更多相关文章

  1. spring的容器(控制反转、依赖注入)

    一.spring的容器 ”容器“是spring的一个重要概念,其主要作用是完成创建成员变量,并完成装配. 而容器的特点”控制反转“和”依赖注入“是两个相辅相成的概念. 控制反转:我们在使用一个类型的实 ...

  2. Spring框架之控制反转和依赖注入

    学Spring框架必须理解控制反转和依赖注入.下面各自举一个例子,来说明控制反转和依赖注入. IOC(控制反转):应用本身创建和维护的依赖对象:现在交由外部容器(Spring)来创建和维护:这个控制权 ...

  3. spring 控制反转与依赖注入原理-学习笔记

    在Spring中有两个非常重要的概念,控制反转和依赖注入:控制反转将依赖对象的创建和管理交由Spring容器,而依赖注入则是在控制反转的基础上将Spring容器管理的依赖对象注入到应用之中: 所谓依赖 ...

  4. Spring学习之Ioc控制反转(1)

    开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...

  5. Spring学习之Ioc控制反转(2)

    开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...

  6. Spring理论基础-控制反转和依赖注入

    第一次了解到控制反转(Inversion of Control)这个概念,是在学习Spring框架的时候.IOC和AOP作为Spring的两大特征,自然是要去好好学学的.而依赖注入(Dependenc ...

  7. 【Spring Framework】Spring 入门教程(一)控制反转和依赖注入

    参考资料 Spring 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...

  8. 轻松了解Spring中的控制反转和依赖注入(二)

    紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...

  9. 轻松了解Spring中的控制反转和依赖注入(一)

    我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达170平方米,重达30吨,到现如今的个人笔记本,事物更加轻量功能却更加丰富,这是事物发展过程中的一个趋势,在技术领域中同样也是如此,企业级Ja ...

随机推荐

  1. 深入理解 JavaScript 异步系列(4)—— Generator

    第一部分,ES6 中的 Generator 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6532713.html 未经作者允许不得转载~ 在 ES6 出现 ...

  2. UI 基本控件使用

    一>UITextFiled  ———>UITextField是什么 UITextField ( 输入框 ) : 是控制文本输入和显示的控件.在APP中UITextField 出现频率很高 ...

  3. requireJS的配置心得

    1.html页面中如果同时存在data-main和require()和配置(config中的baseUrl),那么定义根路径 baseUrl > data-main > index.htm ...

  4. Microsoft Visual Studio 2017 安装过程

    工欲善其事必先利其器 Visual Studio 2017 正式版官方下载地址:https://www.visualstudio.com/downloads/ 安装vs2017的时候最好关闭已打开的v ...

  5. 【故障•监听】TNS-12518、TNS-00517和 Linux Error:32:Broken pipe

    [故障|监听]TNS-12518.TNS-00517和 Linux Error:32:Broken pipe 1.1  BLOG文档结构图 1.2  前言部分 1.2.1  导读和注意事项 各位技术爱 ...

  6. Python--定时给Ta讲笑话

    受到这篇文章的启发http://python.jobbole.com/84796/,我也动手写了个程序玩一玩. 接口请求说明: 接口请求地址http://api.1-blog.com/biz/bizs ...

  7. OpenCV使用FindContours进行二维码定位

    我使用过FindContours,而且知道有能够直接寻找联通区域的函数.但是我使用的大多只是"最大轮廓"或者"轮廓数目"这些数据.其实轮廓还有另一个很重要的性质 ...

  8. 开发使用Node.js的一个小技巧

    Node.js作为可以在服务器端运行的一门语言,其处理长连接.多请求的优势受到各大编程爱好者的追捧. 但是在开发调试方面却极为不方便,因为每次改动代码后,都需要终止当前进程,重启服务器.supervi ...

  9. python遍历一个目录,输出所有文件名

    python遍历一个目录,输出所有文件名 python os模块 os import os  def GetFileList(dir, fileList):  newDir = dir  if os. ...

  10. [敏捷开发实践](2) 用于开发和维持复杂产品的敏捷开发框架Scrum

    [敏捷开发实践](2) 用于开发和维持复杂产品的敏捷开发框架Scrum 1,Scrum概述 上篇中提到敏捷开发有两种主流的方法,一个是XP,另一个是Scrum,本篇简要介绍Scrum方法.Scrum是 ...