Spring依赖注入(DI)详解
一.依赖简介
一个典型的企业应用程序不是由一个单一的对象组成(或Spring的说法中的bean)。即使是最简单的应用程序也只有几个对象一起工作来呈现最终用户看作是一个连贯的应用程序。如何从定义许多独立的bean定义到完全实现的应用程序,在这些应用程序中对象协作实现目标。
有关spring的设计模式和应用详情可以参考我这篇文章《spring常用设计模式及应用》
二.依赖注入
依赖注入(DI)是一个过程,通过这个过程,对象可以通过构造函数参数,工厂方法的参数或者在构造或返回对象实例后设置的属性来定义它们的依赖关系从工厂方法。然后容器在创建bean时注入这些依赖关系。这个过程从根本上说是相反的,因此名为控制反转(IoC),它本身通过使用类的直接构造或服务定位符模式来控制它自己的依赖关系的实例化或位置。
代码与DI原则相比更加清晰,当对象提供依赖时,解耦更为有效。该对象不查找它的依赖关系,不知道依赖关系的位置或类。因此,您的类变得更容易测试,特别是当依赖关系在接口或抽象基类上时,它们允许在单元测试中使用存根或模拟实现。
DI存在两种主要的变体,基于构造函数的依赖注入和基于Setter的依赖注入
三.基于构造函数的依赖注入
基于构造器的 DI通过容器调用具有多个参数的构造器来完成,每个参数表示一个依赖关系。调用static具有特定参数的工厂方法来构造这个bean几乎是等价的,而且这个讨论同样将参数作为构造函数和static工厂方法来处理。以下示例显示了只能通过构造函数注入进行依赖注入的类。请注意,这个类没有什么特别之处,它是一个POJO,它不依赖于容器特定的接口,基类或注释。
public class SimpleMovieLister {
private MovieFinder movieFinder; public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder; } } |
1.构造器参数匹配
构造函数参数解析匹配使用参数的类型进行。如果bean定义的构造函数参数中没有潜在的歧义,那么bean定义中定义构造函数参数的顺序就是在实例化bean时将这些参数提供给适当构造函数的顺序。
package x.y; public class Foo {
public Foo(Bar bar, Baz baz) {
// ... } } |
没有潜在的歧义存在,假设Bar和Baz不是继承关系。因此,以下配置好,你不需要指定构造器参数指标明确在<constructor-arg> 索引,类型或类型。
<beans> <bean id="foo" class="x.y.Foo"> <constructor-arg ref="bar"/> <constructor-arg ref="baz"/> </bean> <bean id="bar" class="x.y.Bar"/> <bean id="baz" class="x.y.Baz"/> </beans> |
在前面的场景中,如果使用类型属性显式地指定构造函数参数的类型,容器可以使用与简单类型的类型匹配。
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean> |
使用索引属性指定显式构造函数参数的指数。
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean> |
同样也可以使用构造器参数名称匹配
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg name="years" value="7500000"/> <constructor-arg name="ultimateAnswer" value="42"/> </bean> |
2.基于Setter方法
在调用无参数构造函数或无参数静态工厂方法实例化bean时,基于bean的调用Setter方法是通过bean调用Setter方法完成的。
public class SimpleMovieLister {
private MovieFinder movieFinder; public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder; } } |
Spring团队通常提倡构造函数注入,因为它使一个能够将应用程序组件作为不可变对象实现,并确保所需的依赖项不是null。此外,构造函数注入的组件总是返回到完全初始化状态的客户机(调用)代码中。作为一个方面说明,大量的构造函数的参数是一个糟糕的代码的气味,这意味着类可能有太多的责任和应该被更好的问题解决的适当分离。
Setter注入应该主要用于可选的依赖关系,这些依赖关系可以在类中分配合理的默认值。否则,非空检查必须在代码使用依赖项的任何地方执行。第=一个优势就是在于setter方法使该类的对象能够重新配置或重新注入。因此通过JMX MBean管理是setter注入一个引人注目的用例.
Spring依赖注入(DI)详解的更多相关文章
- Spring 依赖注入方式详解
平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想,即依赖类不由 ...
- Spring 依赖注入方式详解(四)
IoC 简介 平常的Java开发中,程序员在某个类中需要依赖其它类的方法. 通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. Spring提出了依赖注入的思想 ...
- Unity依赖注入使用详解
写在前面 构造器注入 Dependency属性注入 InjectionMethod方法注入 非泛型注入 标识键 ContainerControlledLifetimeManager单例 Unity注册 ...
- SpringDI四种依赖注入方式详解
文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! LOGO SpringDI(依赖注入) 一.DI概述 De ...
- Spring IOC 注入方式详解 附代码
引言 Spring框架作为优秀的开源框架之一,深受各大Java开发者的追捧,相信对于大家来说并不陌生,Spring之所以这么流行,少不了他的两大核心技术IOC和IOP.我们这里重点讲述Spring框架 ...
- .NET Core 中依赖注入框架详解 Autofac
本文将通过演示一个Console应用程序和一个ASP.NET Core Web应用程序来说明依赖注入框架Autofac是如何使用的 Autofac相比.NET Core原生的注入方式提供了强大的功能, ...
- AngularJS开发指南10:AngularJS依赖注入的详解
依赖注入是一种软件设计模式,用来处理代码的依赖关系. 一般来说有三种方法让函数获得它需要的依赖: 它的依赖是能被创建的,一般用new操作符就行. 能够通过全局变量查找依赖. 依赖能在需要时被导入. 前 ...
- Spring 依赖注入(DI) 的三种方式 和 对集合类型的注入
// 分别省略了getter setter public class Student { private String name; private int age; private Teacher t ...
- 依赖注入(IOC) 详解
https://blog.csdn.net/qq_27093465/article/details/52547290 https://blog.csdn.net/qq_27093465/article ...
- 1.4 Spring 依赖注入(DI)和控制反转(IOC)详解
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: https://www.cnblogs.com/bclshuai/p/11380657.html 1.1 Spring 依赖注 ...
随机推荐
- Vue源码学习(一)———数据双向绑定 Observer
从最简单的案例,来学习Vue.js源码. <body> <div id='app'> <input type="text" v-model=" ...
- ES查询-term VS match (转)
原文地址:https://blog.csdn.net/sxf_123456/article/details/78845437 elasticsearch 中term与match区别 term是精确查询 ...
- VSCode的使用
前后端分离的,先打开vs,打开你的项目,在项目根目录中找到.vs文件加,找到.vs\config\applicationhost.config,然后打开找到你项目的IIS Express配置,例如:& ...
- 关于webservlet 请求异步处理,链接未关闭出现的bug
webservlet +redis 的消息发布订阅 ,挺好的 当请求到来,向redis server申请一个频道 ,然后等着另一端架设是B 处理完毕获得到处理信息调用redis ,使用redis 往 ...
- Python读取excel表的数据
from openpyxl.reader.excel import load_workbook #读取xlsx文件def readExcelFile(path): dic={} #打开文件 file= ...
- Java Swing实现展示数据,以及过滤排序
public class RelationCostctrTable extends DefaultTableModel { public RelationCostctrTable(Vector< ...
- 解决js数组循环删除出错
for(var i=0,flag=true,len=arr.length;i<len;flag ? i++ : i){ if( arr[i]&&arr[i].status==0 ...
- mysqlGTID主从配置
GTID主从简介 GTID是基于mysql生成的事务ID,由服务器ID和事务ID组成. 这个ID在主库及从库上都是唯一的. 这个特性可以让mysql的主从复制变得更加简单,一致性更加可靠. GTID优 ...
- ORB-SLAM2的安装和运行流程
一.ORB-SLAM2安装 1.在https://github.com/raulmur/ORB_SLAM2上git clone到当前文件夹内,若想下载到指定文件夹内,就需要cd进入指定文件内,然后再g ...
- shutil模块和os模块对比
一.shutil -- 是一种高层次的文件操作工具类似于高级API,而且主要强大之处在于其对文件的复制与删除操作更是比较支持好. 1.shutil.copy(src,dst)复制一个文件到另一个目录下 ...