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 ...
随机推荐
- Cocos2d-x 之大牛看法
(未完毕) cocos2d-x并非一个适合网游client(mmo)的游戏引擎.越是大型游戏,这个小引擎就越无法驾驭(尽管它很受欢迎). 之前我在原来的公司使用的是自主研发的C3引擎,已经对外开放(尚 ...
- 32款iOS开发插件和工具介绍[效率]
插件和工具介绍内容均收集于网络,太多了就不一一注明了,在此谢过! 1.Charles 为了调试与server端的网络通讯协议.经常须要截取网络封包来分析. Charles通过将自己设置成系统的网络 ...
- bootstrap之Orientation
Orientation 调整屏幕方向的操作. package io.appium.android.bootstrap.handler; import android.os.RemoteExceptio ...
- js04---object1
我们目前为止大多数引用类型都是Object类型的实例,Object也是ECMAScript中使用最多的一种类型(就像java.lang.Object一样,Object类型是所有它的实例的基础).Obj ...
- android-Preference 风格调整
<CheckBoxPreference android:defaultValue="false" android:layout="?android:attr/pre ...
- Error: org.apache.mahout.math.CardinalityException: Required cardinality 10 but got 30问题解决办法
问题详情 在运行mahout中kmeans算法时,采取的是其默认输入路径/user/hadoop/testdata 和 默认输出路径/user/hadoop/output. [hadoop@djt00 ...
- WPF 入门《常用控件》
1.GroupBox 注意: GroupBox仍然需要布局容器来放置元素.如: StackPanel面板 <GroupBox Header="select number?"& ...
- ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接
原文:ASP.NET Core 2.2 十九. 你扔过来个json,我怎么接 前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.in ...
- 00089_字节输出流OutputStream
1.字节输出流OutputStream (1)OutputStream此抽象类,是表示输出字节流的所有类的超类.操作的数据都是字节,定义了输出字节流的基本共性功能方法: (2)输出流中定义都是写wri ...
- HTTP网络协议(四)
确保Web安全的HTTPS HTTP存在三个比较明显的缺点: 通信使用明文(不加密),内容可能会被窃听. 不验证通信方的身份,因此有可能遭遇伪装. 无法证明报文的完整性,所以可能已遭篡改. 尽管HT ...