简单了解Spring的控制反转和依赖注入
浅谈控制反转(Inversion of Control,IOC)
我们首先先来了解一下控制二字,也就是在控制“正”转的情况下,在任何一个有请求作用的系统当中,至少需要有两个类互相配合工作,在一个入口类下使用new关键字创建另一个类的对象实例,这就好比在面向对象编程的思想下,“我“充当一个入口类,在这个入口类中,我每次吃饭的时候都要买一双一次性筷子(每一次使用都要new一次),在这样的关系下,是”我“(即调用者)每次都要”主动“去买一次性筷子(另一个类),我对筷子说你老老实实的过来我的手上,是我控制了筷子,那好,在这种控制正转的关系下,放在现实生活当中,肯定是不现实的,而且人是懒惰的,他总会去创造出更加方便自己生活的想法,更确切的做法是,买一双普通的筷子(非一次性),把他放在一个容器当中(在Spring中叫做IOC容器),你需要使用的时候就对容器说:IOC我想要用筷子(向容器发出请求),接着筷子就会”注入“到的手上,而在这个过程当中,你不再是控制方,反而演变成一名请求者(虽然本身还是调用者),依赖于容器给予你资源,控制权坐落到了容器身上,于是这就是人们俗称的控制反转。
初涉依赖注入(Dependency Injection)
同样接着上面的例子,在控制反转的统一下,筷子是怎么来到我的手上(即我们是如何获得请求的类),这就是一个依赖注入的过程。
再谈IOC与DI
设计原则中好莱坞原则描述到,“别找我们,我们找你”,百度百科上对这点描述是“不要给我们打电话,我们会给你打电话(don‘t call us, we‘ll call you)”这是著名的好莱坞原则。在好莱坞,把简历递交给演艺公司后就只有回家等待。由演艺公司对整个娱乐项的完全控制,演员只能被动式的接受公司的差使,在需要的环节中,完成自己的演出。这一点完美的提现了在IOC身上,IOC所注重的是设计思想上,从一个常规的创建对象的做法,即new一个对象,转变成向IOC容器递交”简历“,被动的等待IOC容器返回资源给你。控制反转即指的是”演艺公司控制演员“,而说到依赖,则是“演员需要公司混饭”,我们所需求的对象,需要依赖容器来获得,这个过程即是依赖注入。本质上IOC和DI是同一思想下不同维度的表现。
代码实现
既然说在控制反转中获取资源的过程叫做依赖注入,那么这里代码实现也是专注于依赖注入。依赖注入有3种方式,分别为构造注入,设置注入,接口注入。
1.接口注入:在接口中定义要注入的信息,并通过接口来完成注入。(Spring不支持这种注入方式--不支持的原因是--Spring声称其是非入侵式的《离开这个框架也能活》,如果使用接口注入的话,就违背了这一原则),这里不做代码实现讲解。
2.setter注入
我们先脱离Spring来实现setter注入,分两步,第一步我们先看看在常规的做法下类之间的关系,第二步使用IOC来进行设计类,对比一下之间的差别。
在常规的做法下

public class UserDao{
public void addUser(String username)
{
System.out.println("添加用户:"+username);
}
}


public class UserMessage {
String username="demo";
UserDao userDao;
public UserMessage(){
userDao=new UserDao();
}
public void addUser(){
userDao.addUser(username);
}
}

public class test{
UserMessage userMessage=new UserMessage();
userMessage.addUser();
}
这上面的代码存在一个缺陷,由于在UserMessage内部创建了UseDao对象,这就造成了两个类之间的耦合度较高,当项目经理想要用另外一个Dao类的方法来实现addUser的时候,这个时候我就需要修改User Message的代码,重新new另一个类,如果系统中有一百个地方用到这个类,那我们这些地方都要全部修改,出现Bug的概率将大大增加,然后过了一阵子,项目经理又说我想换回以前的Dao类了……
下面我们看看IOC设计的实现
public interface UserDao{
void addUser(String username);
}

public class UserDaoImpl implements UserDao{
@Override
public void addUser(String username)
{
System.out.println("添加用户:"+username);
}
}


public class UserMessage{ private UserDao userDao; //使用设值方式赋值
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void addUser(String userName, String password) { userDao.addUser(userName);
}
}


public class test{
public static void main(String[] args) {
UserDao userDao =new UserDaoImpl();
UserMessage userMessage=new UserMessage();
userMessage.setUserDao(userDao);
}
}

我们仔细观察这里的做法, UserDao userDao=new UserDaoImpl()做法,这里就不得不提到了多态,即父类可以引用子类的方法,在这里形成的一个效果就是降低了User Message和UserDao的耦合度。因为UserMessage和UserDao之间仅存在做什么事(addUser方法)的联系,User Message并不了解UserDaoImpl的实现方式。当我们需要换另一种UserDao的实现类的话,我们只需要修改test类下的第一行的代码就可以了,UserMessage内部并不需要修改。
再想想,读者可能会说不对啊,你说的控制反转和依赖注入需要向容器请求资源,这个容器并没有在上面提现出来啊,下面我们就讲解一下Spring 中是如何做到注入的。

<!-- 使用spring管理对象的创建,还有对象的依赖关系 -->
<bean id="userManager" class="scau.zzf.service.UserMessage">
<!-- (1)UserMessageImpl使用了userDao,Ioc是自动创建相应的UserDao实现,都是由容器管理-->
<!-- (2)在UserMessageImpl中提供构造函数,让spring将UserDao实现注入(DI)过来 -->
<!-- (3)让spring管理我们对象的创建和依赖关系,必须将依赖关系配置到spring的核心配置文件中 -->
<property name="userDao" ref="UserDao"></property>
<!-- 构造注入 -->
<!-- <constructor-arg ref="userDao"/> -->
</bean>
<bean id="UserDao" class="scau.zzf.Dao.UserDao"> </bean>

首先我们需要装配Bean,即在Spring容器中将Bean进行配置后,然后返回Bean对象实例。我们可以通过XmlBeanFactory读取我们xml文件,从而获取相关的Bean信息。

public class test {
public static void main(String[] args) throws Exception {
BeanFactory factory=new XmlBeanFactory(new FileSystemResource("src/appllication.xml"));
UserMessage userMessage=(UserMessage)factory.getBean("UserMessage");
userMessage.add("德玛西亚"); }
}

在实际应用当中,我们并不会手动去读取Xml中的信息或者加载配置文件,Spring底层已经帮我做好了这些,也就是在实际应用当中,我们就只是需要发送一个请求而已,当然了解这么一个过程还是很有必要的。
下面再简单讲解一下如何通过注解来实现注入。

@Configuration
public class UserConfig {
@Bean
public UserDao getUserDao(){
return new UserDao();
}
@Bean
public UserMessage getUserMessage(){
return new UserMesssgae(getUserDao);
}
}

@Configuration的作用是使整个类成为一个配置类,@Bean注解会告诉Spring这个注解下的方法将会返回一个对象,这个对象要注册维Spring应用上下文的Bean。在默认情况下,Spring的Bean都是单例的,也就是再上面的例子当中,无论我们使用多少次getUserDao(),结果返回的对象至始至终都是相同的。关于JavaConfig的配置进一步相关说明,读者可以前往笔者的另一篇文章《更加优雅的配置SSH》中进行参考。
转载请说明原文链接:http://www.cnblogs.com/xxzhuang/p/5948902.html 多谢合作。
简单了解Spring的控制反转和依赖注入的更多相关文章
- Spring的控制反转和依赖注入
Spring的官网:https://spring.io/ Struts与Hibernate可以做什么事? Struts, Mvc中控制层解决方案 可以进行请求数据自动封装.类型转换.文件上传.效验… ...
- Spring理论基础-控制反转和依赖注入
第一次了解到控制反转(Inversion of Control)这个概念,是在学习Spring框架的时候.IOC和AOP作为Spring的两大特征,自然是要去好好学学的.而依赖注入(Dependenc ...
- spring(3)------控制反转(IOC)/依赖注入(DI)
一.spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control).它把传统上由程序代码直接操控的对象的调用权交给容器.通过容器来实现对象组件的装配和管理. 所谓 ...
- 如何通俗的理解spring的控制反转、依赖注入、面向切面编程等等
之前一直不理解spring的一些基础特性是什么意思,虽然网上的解释也很多,但是由于我比较笨,就是看不懂,知道最近才稍微了解,下面就以通俗讲解的方式记录下来. 前言 假设我是一个没有开店经验的小老板,准 ...
- 【SSH】——spring的控制反转和依赖注入
spring是一个轻量级的容器框架,主要是为了使企业的开发变得简单.高效.无论是从大小还是开销来讲,他都可以算是轻量级的,也是非侵入性的. 下图是spring的框架示意图,说到spring,就不得不提 ...
- Spring、控制反转与依赖注入(概念)
Spring 一个开源的控制反转(Inversion of Control ,Ioc)和面向切面(AOP)的容器框架. 主要目的:简化开发 控制反转(Inversion of Control ,Ioc ...
- spring IOC --- 控制反转(依赖注入)----简单的实例
IoC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的 ...
- Spring 之 控制反转(IoC), 依赖注入(DI)和面向切面(AOP)
关于依赖注入, 这篇博文写的非常简单易懂. https://github.com/android-cn/blog/tree/master/java/dependency-injection 此外, 博 ...
- Spring 1 控制反转、依赖注入
1.1 Spring的核心是控制反转(IoC)和面向切面(AOP) 学习spring之前的开发中通过new创建一个对象,有了spring之后,spring创建对象实例-IoC控制反转,之后需要实例对象 ...
随机推荐
- 【django之分页器】
一.什么是分页功能 二.Django的分页器(paginator) 语法: paginator = Paginator(book_list, 8) #8条一页print("count:&qu ...
- leetCode:461 汉明距离
汉明距离 两个整数之间的汉明距离指的是这两个数字对应二进制位不同的位置的数目. 给出两个整数 x 和 y,计算它们之间的汉明距离. 思路: 当看到"对应二进制位不同的位置的数目"这 ...
- Python进阶_面对对象&面对过程
这节主要讲面对对象与面对过程两种编程思想的主要区别. 一. 简单对比 面向过程是一种基础的方法,它考虑的是实际的实现步骤,一般情况下,面向过程是自顶向下逐步求精,其最重要的是模块化的思想方法. 面向对 ...
- POJ-1256 next_permutation函数应用
字典序列: 在字典序中蕴含着一个点,就是大小的问题,谁先出现,谁后出现的问题.譬如a<b<c,出现顺序就是a,b,c. 本题中字符集是所有大小写字母,而题目中规定的谁大谁小已经不是按asc ...
- 剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略
1.前言 Kubernetes 很火,一大批互联网公司早已领先一步,搭建起专有的 PaaS平台,传统企业们看到的 Kubernetes的趋势,亦不甘落后,在试水的道上一路狂奔-- 虽然,Kuberne ...
- python中super()的一些用法
在看python高级编程这本书的时候,在讲到super的时候,产生了一些疑惑,super在python中的用法跟其他的语言有一些不一样的地方,在网上找了一些资料,发现基本上很少有文章能把我的疑惑讲明白 ...
- 【Python】 list & dict & str
list & dict & str 这三种类型是python中最常用的几种数据类型.他们都是序列的一种 ■ 序列通用操作 1. 分片 s[a:b] 返回序列s中从s[a]到s[b- ...
- Python的几个小程序,其实我觉得可以称作初学时的基础算法
昨天学习的,今天做一下整理,以前学过几天c,感觉什么都没有搞出来,有点泄气,看到Python后试试,从最基本的东西学起,希望不要辜负我的这一点热情. if语句的应用 n=1 while n<5: ...
- (译文)JavaScript基础——JavaScript中的深拷贝
在JavaScript中如何拷贝一个对象? 通过引用调用 function mutate(obj) { obj.a = true; } const obj = {a: false}; mutate(o ...
- C语言第一次作业——输入输出格式
题目1温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代码 #include& ...