Spring发展到现在遵循“约定大于配置”原则,在基本的应用配置上(如数据库配置),建议采用XML配置方式;在业务逻辑处理上,建议采用注解方式。回顾过往,XML配置方式真的让人又爱又恨。所以,本节通篇采用XML配置方式。

1.DI的配置使用

1.1  依赖和依赖注入

传统应用程序设计中所说的依赖一般指“类之间的关系”,那先让我们复习一下类之间的关系:

  • 泛化表示类与类之间的继承关系、接口与接口之间的继承关系;
  • 实现:表示类对接口的实现;
  • 依赖:当类与类之间有使用关系时就属于依赖关系,不同于关联关系,依赖不具有“拥有关系”,而是一种“相识关系”,只在某个特定地方(比如某个方法体内)才有关系。
  • 关联:表示类与类或类与接口之间的依赖关系,表现为“拥有关系”;具体到代码可以用实例变量来表示; 
  • 聚合:属于是关联的特殊情况,体现部分-整体关系,是一种弱拥有关系;整体和部分可以有不一样的生命周期;是一种弱关联;
  • 组合:属于是关联的特殊情况,也体现了体现部分-整体关系,是一种强“拥有关系”;整体与部分有相同的生命周期,是一种强关联;

1.2 IoC容器依赖的含义

Spring IoC容器的依赖有两层含义:Bean依赖容器容器注入Bean的依赖资源

  • Bean依赖容器:也就是说Bean要依赖于容器,这里的依赖是指容器负责创建Bean并管理Bean的生命周期,正是由于由容器来控制创建Bean并注入依赖,也就是控制权被反转了,这也正是IoC名字的由来,此处的有依赖是指Bean和容器之间的依赖关系
  • 容器注入Bean的依赖资源:容器负责注入Bean的依赖资源,依赖资源可以是Bean、外部文件、常量数据等,在Java中都反映为对象,并且由容器负责组装Bean之间的依赖关系,此处的依赖是指Bean之间的依赖关系可以认为是传统类与类之间的“关联”、“聚合”、“组合”关系

1.3 依赖注入的好处

为什么要应用依赖注入,应用依赖注入能给我们带来哪些好处呢?

  • 动态替换Bean依赖对象,程序更灵活:替换Bean依赖对象,无需修改源文件:应用依赖注入后,由于可以采用配置文件方式实现,从而能随时动态的替换Bean的依赖对象,无需修改java源文件;
  • 更好实践面向接口编程,代码更清晰:在Bean中只需指定依赖对象的接口,接口定义依赖对象完成的功能,通过容器注入依赖实现;
  • 更好实践优先使用对象组合,而不是类继承:因为IoC容器采用注入依赖,也就是组合对象,从而更好的实践对象组合。

采用对象组合,Bean的功能可能由几个依赖Bean的功能组合而成,其Bean本身可能只提供少许功能或根本无任何功能,全部委托给依赖Bean,对象组合具有动态性,能更方便的替换掉依赖Bean,从而改变Bean功能;

而如果采用类继承,Bean没有依赖Bean,而是采用继承方式添加新功能,,而且功能是在编译时就确定了,不具有动态性,而且采用类继承导致Bean与子Bean之间高度耦合,难以复用。

  • 增加Bean可复用性:依赖于对象组合,Bean更可复用且复用更简单;
  • 降低Bean之间耦合:由于我们完全采用面向接口编程,在代码中没有直接引用Bean依赖实现,全部引用接口,而且不会出现显示的创建依赖对象代码,而且这些依赖是由容器来注入,很容易替换依赖实现类,从而降低Bean与依赖之间耦合;
  • 代码结构更清晰:要应用依赖注入,代码结构要按照规约方式进行书写,从而更好的应用一些最佳实践,因此代码结构更清晰。

由此可以看出,其实依赖注入只是一种装配对象的手段,设计的类结构才是基础,如果设计的类结构不支持依赖注入,Spring IoC容器也注入不了任何东西,从而从根本上说“如何设计好类结构才是关键,依赖注入只是一种装配对象手段”。


2.依赖注入实现方式

前边IoC一章我们已经了解了Bean依赖容器,那容器如何注入Bean的依赖资源,Spring IoC容器注入依赖资源主要有以下两种基本实现方式:

  • 构造器注入:就是容器实例化Bean时注入那些依赖,通过在在Bean定义中指定构造器参数进行注入依赖,包括实例工厂方法参数注入依赖,但静态工厂方法参数不允许注入依赖;
  • setter注入:通过setter方法进行注入依赖;
  • 接口注入:

我们已经知道注入实现方式了,接下来让我们来看看具体配置吧。

2.1 构造方法注入

先定义一个汽车类

/*** 依赖注入* 【1】构造方法的注入方式*/
public class Car {private String name;private Double price;public Car(String name, Double price) {this.name = name;this.price = price;}@Overridepublic String toString() {return "Car [name=" + name + ", price=" + price + "]";}}

XML配置:

<!-- ========================依赖注入注入的几种方式========================== -->
<!-- ========================1.使用构造方法的方式注入======================== -->
<!-- 常规构造方法注入 -->
<bean id="car" class="com.hl.spring.ioc.charcater4.Car" >
<!-- <constructor-arg name="name" value="大奔"/><constructor-arg name="price" value="100000"/>
--><constructor-arg index="0" value="奇瑞QQ"/><constructor-arg index="1" value="20000"/>
</bean>

汽车出来,总得有人去开车,造个人出来吧,Person类:

public class Person {private String name;private Car car;public Person(String name, Car car) {super();this.name = name;this.car = car;}@Overridepublic String toString() {return "Person [name=" + name + ", car=" + car + "]";}
}

XML配置文件:

<!-- 构造方法注入,当Java类的属性是另一个Java类时 -->
<bean id="person" class="com.hl.spring.ioc.charcater4.Person"><constructor-arg name="name" value="xiaoming"/><constructor-arg name="car" ref="car"/>
</bean>

2.2 set方法注入

/*** 依赖注入* 【2】set方法的注入方式*/
public class Car2 {private String name;private Double price;public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getPrice() {return price;}public void setPrice(Double price) {this.price = price;}@Overridepublic String toString() {return "Car [name=" + name + ", price=" + price + "]";}
}

XML配置:

<!-- ==========================2.使用Set方法的方式注入========================== -->
<bean id="car2" class="com.hl.spring.ioc.charcater4.Car2"><property name="name" value="赛特"/><property name="price" value="998" />
</bean>

3. 测试

测试类:

public class Test01 {@Testpublic void run(){ApplicationContext context = new ClassPathXmlApplicationContext("/character4.xml");/*【1】构造方法注入*/Car c = context.getBean("car",Car.class);System.out.println("构造方法注入:" + c);/*【1】构造方法注入,Java类的属性是另一个Java类时*/Person person = context.getBean("person",Person.class);System.out.println("构造方法注入:" + person);/*【2】set方法注入*/Car2 car2 = context.getBean("car2",Car2.class);System.out.println("set方法注入:" + car2);}
}

测试结果:

构造方法注入:Car [name=奇瑞QQ, price=2000.0]
构造方法注入:Person [name=xiaoming, car=Car [name=奇瑞QQ, price=2000.0]]
set方法注入:Car [name=赛特, price=998.0]

4. 注入复杂类型

Spring不仅能注入简单类型数据,还能注入集合(Collection、无序集合Set、有序集合List)类型、数组(Array)类型、字典(Map)类型数据、Properties类型数据,接下来就让我们一个个看看如何注入这些数据类型的数据。

/*** 复杂类型的注入*/
public class CollectionBean {private String[] arrs;private List<String> list;private Set<String> set;private Map<String, Integer> map;private Properties properties;public void setArrs(String[] arrs) {this.arrs = arrs;}public void setSet(Set<String> set) {this.set = set;}public void setMap(Map<String, Integer> map) {this.map = map;}public void setProperties(Properties properties) {this.properties = properties;}public void setList(List<String> list) {this.list = list;}@Overridepublic String toString() {return "CollectionBean [arrs=" + Arrays.toString(arrs) + ", list=" + list + ", set=" + set + ", map=" + map+ ", properties=" + properties + "]";}
}

 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"xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- ===================依赖注入注入,注入复杂类型=========================== --><!-- properties标签中的name名称需要与CollectionBean类中对应变量的名称一致 --><bean id="collectionBean" class="com.hl.spring.ioc.charcater5.CollectionBean"><!-- ========================注入数组======================== --><property name="arrs"><list><value>哈哈</value><value>呵呵</value><value>嘿嘿</value></list></property><!-- ========================注入list======================== --><property name="list"><list><value>小雷</value><value>小风</value><value>小雨</value></list></property><!-- =======================注入set集合======================= --><property name="set"><set><value>set</value><value>集合</value></set></property><!-- =======================注入map集合======================= --><property name="map"><map><entry key="map01" value="1"></entry><entry key="map02" value="2"></entry><entry key="map03" value="3"></entry></map></property><!-- ==================注入properties属性文件================== --><property name="properties"><props><prop key="uname">root</prop><prop key="pass">123</prop></props></property></bean><!-- ===============依赖注入注入,引入其他的xml配置文件=============== --><!-- <import resource="character2.xml"/> --></beans>

测试类:

public class Test05 {@Testpublic void run(){ApplicationContext context = new ClassPathXmlApplicationContext("/character5.xml");CollectionBean bean = context.getBean("collectionBean",CollectionBean.class);System.out.println("复杂类型注入:" + bean);}
}

测试结果:

复杂类型注入:
CollectionBean [arrs=[哈哈, 呵呵, 嘿嘿],list=[小雷, 小风, 小雨],set=[set, 集合], map={map01=1, map02=2, map03=3}, properties={uname=root, pass=123}
]

5. 配置简写

让我们来总结一下依赖注入配置及简写形式,其实我们已经在以上部分穿插着进行简化配置了:

5.1 构造器注入

1)常量值

简写:<constructor-arg index="0" value="常量"/>

全写:<constructor-arg index="0"><value>常量</value></constructor-arg>

2)引用

简写:<constructor-arg index="0" ref="引用"/>

全写:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>


5.2 setter注入

1)常量值

简写:<property name="message" value="常量"/>

全写:<property name="message"><value>常量</value></ property>

2)引用

简写:<property name="message" ref="引用"/>

全写:<property name="message"><ref bean="引用"/></ property>

3)数组:<array>没有简写形式

4)列表:<list>没有简写形式

5)集合:<set>没有简写形式

6)字典

简写:

<map>

<entry key="键常量" value="值常量"/>

<entry key-ref="键引用" value-ref="值引用"/>

</map>

全写:

<map>

<entry><key><value>键常量</value></key><value>值常量</value></entry>

<entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>

</map>

7)Properties:没有简写形式


5.3 使用p命名空间简化setter注入

使用p命名空间来简化setter注入,具体使用如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="bean1" class="java.lang.String"><constructor-arg index="0" value="test"/></bean>
<bean id="idrefBean1" class="cn.javass.spring.chapter3.bean.IdRefTestBean"
p:id="value"/>
<bean id="idrefBean2" class="cn.javass.spring.chapter3.bean.IdRefTestBean"
p:id-ref="bean1"/>
</beans>
  • xmlns:p="http://www.springframework.org/schema/p" :首先指定p命名空间
  • <bean id="……" class="……" p:id="value"/> :常量setter注入方式,其等价于<property name="id" value="value"/>
  • <bean id="……" class="……" p:id-ref="bean1"/> :引用setter注入方式,其等价于<property name="id" ref="bean1"/>

(4)Spring框架----依赖注入(DI)相关推荐

  1. Spring框架—③依赖注入DI、Bean作用域及自动装配

    依赖注入 DI,Dependency injection 依赖: 指bean对象的创建依赖于Spring容器 注入: 指Bean对象所依赖的资源,由容器来设置和装配 在beans.xml中配置 1.常 ...

  2. 框架学习 Spring之依赖注入DI

    依赖注入的方式有四种: 1.Setter注入(属性注入) 2.构造器注入 3.P命名空间注入 4.集合类型值注入 1.Setter注入(属性注入) Employee 员工实体类 package com ...

  3. Spring字段依赖注入示例

    学习如何编写Spring Field Injection示例 . 字段注入是Spring框架 依赖注入的一种 . 在本教程中,我们将编写几个类,并看一看现场注入工程. 有关Spring依赖注入的更多信 ...

  4. Spring的依赖注入(DI)和面向切面(AOP)代码解析说明

    转载自: https://www.cnblogs.com/zmmi/p/7922186.html 1 依赖注入(DI)  大部分的Spring的新手(我)在学习之初对依赖注入这个词感到迷茫,事实上它并 ...

  5. java-12:spring MVC - 控制反转IOC,依赖注入DI

    学习spring框架之前,先理解几个概念: 1.第一部分:依赖倒置原则 2.第二部分:控制反转,控制反转容器(实例) 3.第三部分:控制反转,控制反转容器(全面理解,面试题) 综合性理解:控制反转(I ...

  6. 框架源码系列九:依赖注入DI、三种Bean配置方式的注册和实例化过程

    一.依赖注入DI 学习目标 1)搞清楚构造参数依赖注入的过程及类 2)搞清楚注解方式的属性依赖注入在哪里完成的. 学习思路 1)思考我们手写时是如何做的 2)读 spring 源码对比看它的实现 3) ...

  7. spring 04-Spring框架依赖注入基本使用

    Spring的依赖注入形式实际上所有对象产生控制都要通过applicationContext.xml文件实现 依赖注入必须启动容器后才可以进行该配置文件的内部的加载操作 依赖注入之有参构造 定义一个D ...

  8. Spring框架----Spring的依赖注入

    1.spring的依赖注入的概念 依赖注入:dependency Injection IOC的作用:降低程序之间的依赖关系,但不是消除. 依赖关系的管理:以后都交给了spring来维护 在当前类中需要 ...

  9. 框架依赖注入和普通依赖注入_依赖注入快速入门:它是什么,以及何时使用它...

    框架依赖注入和普通依赖注入 by Bhavya Karia 通过Bhavya Karia 介绍 (Introduction) In software engineering, dependency i ...

  10. 控制反转IOC与依赖注入DI

    为什么80%的码农都做不了架构师?>>>    1. IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最 ...

最新文章

  1. python全栈开发中级班全程笔记(第二模块、第四章)(常用模块导入)
  2. UVa11137 Ingenuous Cubrency
  3. 记录执行hivesql时报org.apache.hadoop.hdfs.BlockMissingException:Could not obtain block错误
  4. HTML页面之间跳转与传值(JS代码)
  5. mysql查询时传入中文时的乱码问题
  6. Ubuntu技巧之xxx is not in the sudoers file解决方法
  7. oracle如何增加磁盘,牛刀小试Oracle之ORACLE 11GR2 RAC安装配置-asm磁盘组配置添加(四)...
  8. 图像去雾:基于暗通道的去雾算法 - 附代码
  9. web前端常用开发工具排行:8款html开发工具推荐下载
  10. 春节怎么抢红包,python一招告诉你再也不会错过微信红包
  11. 云计算与大数据作业 21大数据 刘佳琪
  12. Rhythmbox中文乱码解决
  13. 小米关机一直显示android,小米手机一直卡在fastboot怎么办
  14. 数据分析神器Alteryx
  15. 和平精英灵敏度分享码服务器没有响应,不求人灵敏度分享码 和平精英最新吃鸡灵敏度...
  16. CDR类CAD制作室内装修平面图
  17. 使用wcf编写坐标字符串生成shapefile文件,在iis发布供前端调用
  18. 找不到wpcap.dll解决方法
  19. cmd批量打开网页和关闭网页的批处理代码
  20. 系统管理员设置了系统策略,禁止进行此安装。

热门文章

  1. 面试题之浅克隆和深克隆
  2. spring源码-第四个后置处理器
  3. Spring的注入方式中,官方推荐哪种方式
  4. MyBatis中foreach的用法
  5. 微信小程序事件绑定无效
  6. Mac、centos安装MongoDB
  7. [转载] 民兵葛二蛋——第7集
  8. Hibernate学习(八):检索方式
  9. static 和 const的解释(转载)
  10. [VC] 通过IHTMLDocument2-DC把网页保存为图片