spring入门学习笔记第三课--spring的注入
来源:互联网 发布:一键复制淘宝店铺 编辑:程序博客网 时间:2024/06/10 15:55
spring的一个核心功能就是依赖注入,有的叫依赖注入(DI),也有的叫控制反转(IOC),但实际上在某种程度上,他们是差不多的。
我学习spring接触到的第一个概念就是DI,
通俗的解释就是:
在我们常规编程中,如果需要使用某个的方法,我们通常会new一个该对象的实例,然后调用方法,就像这样:
现有A和B两个类,我们想要在B类中调用的methodA方法。
Object Apublic class A{/** *这是我们想要调用的方法 **/public void methodA(){ //逻辑....}}}
我们通常在B类中会这样用:
public class B{public void methodB(){//我们会先new一个A的对象A a=new A();//然后调用A的方法a.methodA();}}这种是比较常规的方法,即:如果我们使用某个对象的方法,我们需要手动创建这个对象。
但是IOC就提供了另外一种思维方式,就是不在由我们去创建这个类,而是由spring去创建这个类。
举一个生活中简单的例子,
在以前,如果我们需要一件新衣服,我们往往会这样做:
去布店裁点布,然后我们回家自己做。
也就是说,如果我们需要新衣服,我们需要自己做。
但是现在就不同了,现在如果我们需要一件新衣服,我们可以通过各种渠道购入,比如网上购物,比如商场。
这样,当我们需要新衣服的时候,我们就不需要自己去做了,相对于以前,不仅省了大量的时间,而且衣服的款式也多种多样。
回到spring这里,其实这里spring就承担类似于商场或者网店这样的角色,
我们不需要自己去做衣服,我们只要告诉spring我们需要什么样的衣服,spring会自动给我们提供。
如果放到代码里,大概就是这个样子的。
首先,我们需要构建一个spring项目:
项目的结构如下:
首先定义一个服装的接口,这个接口定义了如何展示这件衣服:
package com.panda.clothes.inter;/** * 定义服装接口 * @author Panda * */public interface BaseClothes {/** * 展示衣服的方法 */public void showClothes();}然后,编写两个类,分别实现服装接口。
package com.panda.clothes.inter.impl;import com.panda.clothes.inter.BaseClothes;/** * 西装类 * 该类实现了衣服的接口 * @author Panda * */public class BusinessSuit implements BaseClothes {public void showClothes() {System.out.println("Clothes`s Name:"+"BusinessSuit");System.out.println("Clothes`s price:"+"$1000.0");System.out.println("Clothes`s Color:"+"black");}}
package com.panda.clothes.inter.impl;import com.panda.clothes.inter.BaseClothes;/** * T恤衫类 * 该类实现服装接口 * @author Panda * */public class TShirt implements BaseClothes {public void showClothes() {System.out.println("Clothes`s Name:"+"TShirt");System.out.println("Clothes`s price:"+"$150.0");System.out.println("Clothes`s Color:"+"white");}}接下来编写测试类,
首先是我们比较常用的方式:
首先构建一个实例,然后调用方法
/** * 常规的使用方法 */@org.junit.Testpublic void conventionTest(){//首先创建一个服装对象,然后对其赋值。BaseClothes clothes=new BusinessSuit();//然后调用服装的展示方法clothes.showClothes();}运行结果如下:
Clothes`s Name:BusinessSuit
Clothes`s price:$1000.0
Clothes`s Color:black
但是,如果我们突然不想要西装了,我们想要T恤,我们就需要对代码修改
/** * 常规的使用方法 */@org.junit.Testpublic void conventionTest(){//如果此时我们不想要西装,我们想要T恤。我们就需要实例化T恤而不是西装。//BaseClothes clothes=new BusinessSuit();//重新构造BaseClothes clothes=new TShirt();//然后调用服装的展示方法clothes.showClothes();}运行结果如下:
Clothes`s Name:TShirt
Clothes`s price:$150.0
Clothes`s Color:white
这样我们就会发现,当我们对衣服需要变更时,我们需要修改代码。如果只有两件衣服还好一点,但是当业务逻辑更加复杂时,我们很可能都不知道自己需要改多少代码。
但是spring为我们提供了一种优秀的解决办法,也就是DI。
spring的DI有三种,
分别是:
1.接口注入
2.构造注入
3.set注入
首先我们展示第一种注入方式,接口注入,如果我们需要使用接口注入的话,需要提供一个接口,该接口提供被调用类的初始化方法。
package com.panda.clothes.test;import com.panda.clothes.inter.BaseClothes;public interface InterfaceInject { public void CreateClothes(BaseClothes clothes); public BaseClothes getClothes();}然后,任何需要使用clothes实例的类,都要继承这个类
package com.panda.clothes.test;import com.panda.clothes.inter.BaseClothes;public class InterfaceInjectImpl implements InterfaceInject { private BaseClothes clothes; public void CreateClothes(BaseClothes clothes) { this.clothes = clothes; } public BaseClothes getClothes(){ return this.clothes; }}最后,我们编写测试类。
package com.panda.clothes.test;import com.panda.clothes.inter.BaseClothes;import com.panda.clothes.inter.impl.TShirt;public class InterfaceTest {//首先获取clothes的实例InterfaceInject ifi=new InterfaceInjectImpl();@org.junit.Testpublic void test(){ //提供clothes的实例 ifi.CreateClothes(new TShirt()); //获取clothes的实例 BaseClothes clothes=ifi.getClothes(); //调用clothes的展示方法 clothes.showClothes();}}
输出结果如下:
Clothes`s Name:TShirt
Clothes`s price:$150.0
Clothes`s Color:white
这样做有什么作用呢?
在我们常规的方法中,调用类直接依赖被调用类,使用接口注入我们就可以将依赖分离到接口层次,然后具体的实现我们可以通过配置文件或其他方式来加载。
但是这种方式依然具备很强的侵略性,所以实际应用有限。
其实关于接口注入,我也是有点迷糊,似懂非懂的感觉,做个标记,之后等完全弄清楚再回来补一个详细的。
2017/03/03补充:接口注入和注入接口的区别
整理这篇内容的时候,在这我遇到一个问题,就是接口注入和注入接口有什么本质的区别,毕竟看起来这个东西最终的实现和注入接口的方式是一样的,而且还多了一层,更复杂了.
关于这个问题问了好多人,今天终于获得了一个比较通俗的解释,
使用接口注入这种方式,我们可以在中转接口中,定义一些指定的业务处理,做一些校验等操作,类似于服务定位模式.
比直接注入接口多了一层封装.
spring中使用最多的方式就是set注入,setter注入通过提供属性值的getter/setter方法来注入需要的实例。
继续使用之前的BaseClothes接口和BusinessSuit以及TShirt实例。
然后我们新建一个测试类:
在测试类中提供一个BaseClothes参数,并提供她的getter/setter方法。
package com.panda.clothes.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.panda.clothes.inter.BaseClothes;public class SetterTest { //提供BaseClothes字段private BaseClothes clothes; //提供BaseClothes的getter/setter方法public BaseClothes getClothes() { return clothes;}public void setClothes(BaseClothes clothes) { System.out.println("set注入调用属性的setter方法"); this.clothes = clothes;}@org.junit.Testpublic void Test(){ ApplicationContext atc=new ClassPathXmlApplicationContext("spring-demo.xml"); SetterTest ses=(SetterTest) atc.getBean("setterTest"); ses.getClothes().showClothes();}}之后我们在SRC下新建一个spring-demo.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 调用类 --><bean id="setterTest" class="com.panda.clothes.test.SetterTest"><property name="clothes" ref="businessSuit"></property></bean><!-- 服装 --><!-- 西装 --><bean id="businessSuit" class="com.panda.clothes.inter.impl.BusinessSuit" /><!-- T恤 --><bean id="tShirt" class="com.panda.clothes.inter.impl.TShirt"></bean></beans>运行测试类:
set注入调用属性的setter方法
Clothes`s Name:BusinessSuit
Clothes`s price:$1000.0
Clothes`s Color:black
这种在配置文件中通过property属性进行配置则默认采用的set注入。
最后一种注入方式为构造注入:
只需要稍微修改一下配置文件和测试类:
测试类去除getter/setter方法,添加一个构造方法
public class SetterTest {//提供BaseClothes字段private BaseClothes clothes;//提供BaseClothes的getter/setter方法public SetterTest(BaseClothes clothes) {// TODO Auto-generated constructor stubthis.clothes=clothes;}public static void main(String []args){ApplicationContext atc=new ClassPathXmlApplicationContext("spring-demo.xml");SetterTest ses=(SetterTest) atc.getBean("setterTest");ses.clothes.showClothes();}
配置文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 调用类 --><bean id="setterTest" class="com.panda.clothes.test.SetterTest"> <constructor-arg index="0" ref="tShirt" /></bean><!-- 服装 --><!-- 西装 --><bean id="businessSuit" class="com.panda.clothes.inter.impl.BusinessSuit" /><!-- T恤 --><bean id="tShirt" class="com.panda.clothes.inter.impl.TShirt"/></beans>这种通过constructor-arg注入的方法叫做构造注入,他是通过构造方法进行注入。
这三种方法常用的是set注入也叫设置注入,
通过这种方法,我们可以直观明确的了解我们注入的是什么,但是因为我们提供了setter方法,所以我们不能确定相关的数据成员会不会被改变。
而通过构造注入的方法,一方面符合了java的编码规则,在类创建是就得到一个完整的实例,另一方面我们也可以通过构造参数的顺序来控制我们实例化的顺序,但是这种方法当我们需要实例化较多数据时,构造器会比较臃肿,而且参数太多,也不太容易记忆。
- spring入门学习笔记第三课--spring的注入
- (学习笔记)spring入门之Bean的依赖注入
- Spring 学习笔记 ----依赖注入
- [学习笔记]Spring依赖注入
- 学习笔记:Spring注解注入
- Spring学习笔记 依赖注入
- 【Spring学习笔记】依赖注入
- Spring学习笔记(4.Spring注入)
- spring 入门学习笔记
- Spring入门-学习笔记
- Spring入门学习笔记
- Spring入门学习笔记
- spring入门学习笔记第二课--为什么使用spring以及spring的使用
- spring温习笔记-入门-依赖注入
- Spring学习笔记:2-Spring中IoC的入门实例
- Spring学习笔记:Spring中IoC的入门实例
- Spring学习笔记---Spring入门的第一个程序
- [spring入门学习笔记][spring的IoC原理]
- leetcode D1 Hamming Distance
- 二级考试复习随笔
- 读取inputStream中的数据
- 2324: [ZJOI2011]营救皮卡丘
- ELK 聚合查询
- spring入门学习笔记第三课--spring的注入
- 这篇文章为了请教大牛帮忙解决一下现网乱码问题
- 从源码编译TensorFlow出错和解决
- keras学习随笔03——常用keras layers
- 有关ContainsKey方法和containsValue方法的区别,以及原因???
- 闭包
- 【LeetCode 459】 Repeated Substring Pattern
- webService调用天气接口遇见的问题
- select 实现分析