spring(3)------控制反转(IOC)/依赖注入(DI)
一。spring核心概念理解
控制反转:
控制反转即IoC (Inversion of Control)。它把传统上由程序代码直接操控的对象的调用权交给容器。通过容器来实现对象组件的装配和管理。
所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。
没有控制反转这样的模式前。你创建一个对象。在什么地方用。你得单独通过keywordnew出来用,
但如今能够不用这样,你把new对象的权利交给spring配置文件。通过配置文件来'new',
IoC是一个非常大的概念,能够用不同的方式来实现。
其主要实现方式有两种:
(1)依赖查找(Dependency Lookup):容器提供回调接口和上下文环境给组件。
(2)依赖注入(Dependency Injection):组件不做定位查询,仅仅提供普通的Java方法让容器去决定依赖关系。
后者是时下最流行的IoC类型,其又有接口注入(Interface Injection)。设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。
控制反转和依赖注入究竟是什么关系?
控制反转是个模式,是个大概念,而对控制反转最详细的解释就是依赖注入,前者是说个大范围,
后者是详细到这件事情的实质上。
就好比你朋友说等你过生日一定要送你个礼物,等过生日时送了你一个手机,
而送礼物就是个大概念,好比控制反转。详细送了一个手机,就是依赖注入。可是两者说明的是送礼物的这件事。
当然了,依赖注入有三种方式,就好比你朋友能够选择送你个苹果手机或送你台宝马或送你套别墅三种注入方式,
概率没有必要咬文嚼字的去理解,先把车会开了。慢慢就会知道车是怎么组成的。
二,IoC概念实例理解
在写一个程序。有多中实现方式,你假设每次都通过改程序代码。通过new来实现不同的功能,耦合性太高,
IoC是为解决松耦合而生的。下面通过代码理解。
(1)创建接口和实现类
接口:
package com.lanhuigu.spring.impl; public interface ISayHello {
/**
* 讲不同语言
* @return
*/
public String doSay();
}
说中文实现类:
package com.lanhuigu.spring.impl; public class ChHelloImpl implements ISayHello {
private String msg; public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
/**
* 讲汉语
*/
@Override
public String doSay() {
// TODO Auto-generated method stub
return "中文:"+msg;
} }
说英文实现类:
package com.lanhuigu.spring.impl; public class EnHelloImpl implements ISayHello {
private String msg; public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
/**
* 讲英语
*/
@Override
public String doSay() {
// TODO Auto-generated method stub
return "英文:"+msg;
} }
(2)配置spring文件
package com.lanhuigu.spring.impl; public class EnHelloImpl implements ISayHello {
private String msg; public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
/**
* 讲英语
*/
@Override
public String doSay() {
// TODO Auto-generated method stub
return "英文:"+msg;
} }
(3)測试程序
package com.lanhuigu.spring.test; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lanhuigu.spring.impl.ISayHello; public class TestHelloWorld {
@Test
public void testMyHelloWorld(){
//1.读取spring初始化的配置文件
ApplicationContext acxt =
new ClassPathXmlApplicationContext("/applicationContext.xml");
//2.依据bean获取ISayHello实现类对象
ISayHello sayHello = (ISayHello) acxt.getBean("sayHello");
//3.调用接口方法
System.out.println(sayHello.doSay());
}
}
通过以上代码对IoC进行实例体会:
(1)在測试程序中,假设不使用IoC,你能够通过new来实现讲什么语言
ISayHello sayHello = new ChHelloImpl();//讲汉语
ISayHello sayHello = new EnHelloImpl();//讲英语
也许会认为我就new就能够了,领导让我讲英语,我就new讲英语。领导要我讲汉语,我就讲汉语,来回凝视掉即可了,
可是。假设一个应用程序中有一万个地方用到了这段代码, 你是不是得凝视一万个地方,心里绝对10万个对领导不满。改来改去有病吧!
你也许还不服。我就凝视掉一万个地方,假设有100万个地方呢,你是不是100万个'草泥马'在草原上奔腾啊!
这个时候IoC来为你解决烦恼,一剂药就能治好,再也不用操心领导让你说啥你确有苦说不出口了。
通过配置文件控制该讲什么语言:
<bean id="sayHello" class="com.lanhuigu.spring.impl.ChHelloImpl">
<!-- 将变量msg值依赖注入 -->
<property name="msg">
<value>測试</value>
</property>
</bean>
你的配置文件通过实现类配置让讲啥都行。class="com.lanhuigu.spring.impl.ChHelloImpl",
而应用代码不受影响:
ISayHello sayHello = (ISayHello) acxt.getBean("sayHello");
System.out.println(sayHello.doSay());
应用程序仅仅管拿到的bean对象是啥。我就说啥,至于你容器怎么配置。应用程序不屌你,
而容器则配置自己的实现类。至于你应用程序实现成啥样。容器才无论。通过这种关系
实现低耦合的实效,实现控制反转的职能。
三,依赖注入(DI)
依赖注入的含义:
让主键依赖于抽象,当组件要与其它实际对象发生关系时,通过抽象来注入依赖的实际对象。
依赖注入的三种实现方式各自是接口注入(interface injection),set方法注入(setter injection)。构造注入(constructor injection)。
(1)接口注入(interface injection):
定义一个将英语的接口:
package com.lanhuigu.spring.impl; public interface ISayHello {
/**
* 讲英语
* @return
*/
public String doSay(EnHelloImpl en);
}
讲英语接口实现类:
package com.lanhuigu.spring.impl; public class EnHelloImpl implements ISayHello {
private String msg; public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
/**
* 讲英语
*/
@Override
public String doSay(EnHelloImpl en) {
// TODO Auto-generated method stub
return "英文:"+msg;
} }
假设採用接口注入的方式。原本能说各种语言的接口,被定义为仅仅能讲英语的接口。整个业务逻辑类依赖于这个接口。
在spring中接口注入是在IOC概念没有确立时定义的,如今spring中不推荐用接口注入,接口注入业务逻辑类依赖于接口,不是重点。
(2)set方法注入(setter injection):
set注入就是指在接受注入的类中定义一个set方法,并在參数中定义须要注入的參数。
为了可以将多种语言,接口注入方式是不适用的,我们把接口定义成开放的。这样每一个实现类依据须要做自己
的业务逻辑,通过set方法传入參数。
接口:
package com.lanhuigu.spring.impl; public interface ISayHello {
/**
* 讲不同语言
* @return
*/
public String doSay();
}
实现类:
汉语实现类:
package com.lanhuigu.spring.impl; public class ChHelloImpl implements ISayHello {
private String msg; public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
/**
* 讲汉语
*/
@Override
public String doSay() {
// TODO Auto-generated method stub
return "中文:"+msg;
} }
英语实现类:
package com.lanhuigu.spring.impl; public class EnHelloImpl implements ISayHello {
private String msg; public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
/**
* 讲英语
*/
@Override
public String doSay() {
// TODO Auto-generated method stub
return "英文:"+msg;
} }
配置文件传入參数:
<?xml version="1.0" encoding="UTF-8"?> <!--
- Application context definition for JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 定义一个id为sayHello的bean,
通过spring配置文件变换实现类。实现不同的功能,无需改动别的程序 -->
<bean id="sayHello" class="com.lanhuigu.spring.impl.ChHelloImpl">
<!-- 将变量msg值依赖注入 -->
<property name="msg">
<value>測试</value>
</property>
</bean>
</beans>
每个接口实现类相应一种逻辑,spring配置文件负责调配。
配置文件bean的property有个默认属性name,这个name相应的是bean的class类对象中的属性名msg,
代码样式private String msg,value为属性值,通过类中的set方法,将配置文件里的属性值注入,
在类中通过get获取属性值。
(3)构造注入(constructor injection):
构造注入就是在接受注入的类中定义一个构造方法,并在參数中定义须要注入的元素。
咱们将讲英语改成构造方法注入:
接口:
package com.lanhuigu.spring.impl; public interface ISayHello {
/**
* 讲不同语言
* @return
*/
public String doSay();
}
实现类:
package com.lanhuigu.spring.impl; public class ChHelloImpl implements ISayHello {
private String msg;
private String two;
/**
* 构造方法注入
* @param msg
* @param two
*/
public ChHelloImpl(String msg,String two){
this.msg = msg;
this.two = two;
}
/*public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}*/
/**
* 讲汉语
*/
@Override
public String doSay() {
// TODO Auto-generated method stub
return "中文:"+msg+two;
} }
spring配置文件:
<? xml version="1.0" encoding="UTF-8"? > <!--
- Application context definition for JPetStore's business layer.
- Contains bean references to the transaction manager and to the DAOs in
- dataAccessContext-local/jta.xml (see web.xml's "contextConfigLocation").
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<!-- 定义一个id为sayHello的bean,
通过spring配置文件变换实现类,实现不同的功能,无需改动别的程序 -->
<bean id="sayHello" class="com.lanhuigu.spring.impl.ChHelloImpl">
<!-- 将变量msg值依赖注入 -->
<!-- <property name="msg">
<value>測试</value>
</property> -->
<!-- 构造放入注入,
假设不写index,默认构造方法仅仅有一个參数, 假设注入多个。就会报错;
假设注入多个參数,能够通过index的下标指定与构造方法參数的相应关系,
下标从0開始,0表示构造方法的第一个參数,依次类推
-->
<constructor-arg index="0">
<value>測试</value>
</constructor-arg>
<constructor-arg index="1">
<value>two arg</value>
</constructor-arg>
</bean>
</beans>
測试程序:
package com.lanhuigu.spring.test; import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.lanhuigu.spring.impl.ISayHello; public class TestHelloWorld {
@Test
public void testMyHelloWorld(){
//1.读取spring初始化的配置文件
ApplicationContext acxt =
new ClassPathXmlApplicationContext("/applicationContext.xml");
//2.依据bean获取ISayHello实现类对象
ISayHello sayHello = (ISayHello) acxt.getBean("sayHello");
//3.调用接口方法
System.out.println(sayHello.doSay());
}
}
输出结果:
中文:測试two arg
关于构造方法注入的注意点:
(1)在接受注入的构造方法中写须要注入的參数
(2)配置文件里构造属性constructor-arg不写index时默认一个參数,假设构造方法有多个參数,将报错
(3)假设注入多个參数。需在配置文件里constructor-arg通过index明白value相应构造方法中的參数情况
四。总结
依赖注入有三种注入方式,究竟哪种注入方式好。一般推荐使用set注入
接口注入不考虑。构造方法注入通过上面的实例能够看出,假设注入參数太多,
构造方法中就会有一堆參数,看着都迷糊,而spring配置文件还得对參数做相应的传值,
假设注入类太多,參数太多。构造器配置越多,就会迷糊。
而set则是依据名字注入,可以避免构造方法注入的麻烦。可是,使用set方法注入是动态的注入參数。
可能被人篡改。构造方法注入在类启动时就完毕,就不会出现篡改的可能。相对安全性高。二者各有
千秋。可是通经常使用set注入。构造方法注入酌情处理。
来注入的,这一点比构造方法注入好
spring(3)------控制反转(IOC)/依赖注入(DI)的更多相关文章
- Spring 之 控制反转(IoC), 依赖注入(DI)和面向切面(AOP)
关于依赖注入, 这篇博文写的非常简单易懂. https://github.com/android-cn/blog/tree/master/java/dependency-injection 此外, 博 ...
- 依赖倒置原则DIP&控制反转IOC&依赖注入DI
依赖倒置原则DIP是软件设计里一个重要的设计思想,它规定上层不依赖下层而是共同依赖抽象接口,通常可以是上层提供接口,然后下层实现接口,上下层之间通过接口完全透明交互.这样的好处,上层不会因依赖的下层修 ...
- 简单了解Spring的控制反转和依赖注入
浅谈控制反转(Inversion of Control,IOC) 我们首先先来了解一下控制二字,也就是在控制"正"转的情况下,在任何一个有请求作用的系统当中,至少需要有两个类互相配 ...
- Spring理论基础-控制反转和依赖注入
第一次了解到控制反转(Inversion of Control)这个概念,是在学习Spring框架的时候.IOC和AOP作为Spring的两大特征,自然是要去好好学学的.而依赖注入(Dependenc ...
- Spring的控制反转和依赖注入
Spring的官网:https://spring.io/ Struts与Hibernate可以做什么事? Struts, Mvc中控制层解决方案 可以进行请求数据自动封装.类型转换.文件上传.效验… ...
- 如何通俗的理解spring的控制反转、依赖注入、面向切面编程等等
之前一直不理解spring的一些基础特性是什么意思,虽然网上的解释也很多,但是由于我比较笨,就是看不懂,知道最近才稍微了解,下面就以通俗讲解的方式记录下来. 前言 假设我是一个没有开店经验的小老板,准 ...
- Spring 1 控制反转、依赖注入
1.1 Spring的核心是控制反转(IoC)和面向切面(AOP) 学习spring之前的开发中通过new创建一个对象,有了spring之后,spring创建对象实例-IoC控制反转,之后需要实例对象 ...
- 【SSH】——spring的控制反转和依赖注入
spring是一个轻量级的容器框架,主要是为了使企业的开发变得简单.高效.无论是从大小还是开销来讲,他都可以算是轻量级的,也是非侵入性的. 下图是spring的框架示意图,说到spring,就不得不提 ...
- Spring、控制反转与依赖注入(概念)
Spring 一个开源的控制反转(Inversion of Control ,Ioc)和面向切面(AOP)的容器框架. 主要目的:简化开发 控制反转(Inversion of Control ,Ioc ...
随机推荐
- 【翻译自mos文章】OGG的集成捕捉模式支持Oracle database标准版么?
OGG的集成捕捉模式支持Oracle database标准版么? 来源于: Does OGG 11.2.1 Integrated Capture Work with Oracle Database S ...
- cocos2d-x 3.0 Loading界面实现
这个世界每一天都在验证我们的渺小,但我们却在努力创造,不断的在这生活的画卷中留下自己的脚印.或许等到我们老去的那一天,老得不能动仅仅能靠回顾的那一天.你躺在轮椅上,不断的回顾过去.相思的痛苦忘不了,相 ...
- 35.Intellij IDEA设置忽略部分类编译错误
转自:https://www.aliyun.com/jiaocheng/290360.html 有些时候我们的项目中有些错误,但这些错误并不影响项目的整体运行(或许是没有使用到),默认情况下idea是 ...
- Reentrant 可重入解释
作者:知乎用户链接:https://www.zhihu.com/question/37168009/answer/88086943来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...
- 关于EJB--实体Bean的BMP和CMP选择
EJB有两种主要类型BMP(Bean managed persistence )和CMP(Container managed persistence ),这两种类型各有优缺点. BMP是在Bean中完 ...
- js--递归详解
1 函数的调用 eg1:阶乘算法 var f = function (x) { if (x === 1) { return 1; } else { return x * f(x - 1); } }; ...
- BZOJ2244: [SDOI2011]拦截导弹(CDQ分治,二维LIS,计数)
Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度.并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高 ...
- CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)
题目大意: 给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长 解题思路: 假定给你一个字符串,如何判定其经打乱能否 ...
- 【Codeforces Round #452 (Div. 2) A】 Splitting in Teams
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 贪心 1优先和2组队. 如果1没有了 就结束. 如果1还有多余的. 那么就自己3个3个组队 [代码] #include <bi ...
- MySQL 汉字拼音
http://blog.csdn.net/u012076316/article/details/54951365 http://www.cnblogs.com/diony/p/5483108.html ...