依赖注入及AOP简述(三)——依赖注入的原理
3. “依赖注入”登场
于是诸多优秀的IT工程师开始想出了更加轻量便利、更加具有可测试性和可维护性的设计模式——IoC模式。IoC,即Inversion of Control的缩写,中文里被称作“控制反转”。至于为什么会有这么一个看似古怪的名字,我们稍后会做解释。2004年著名软件工程学者和工程师Martin Fowler在其论文《Inversion ofControl Containers and the Dependency Injection pattern》中将IoC更名为DependencyInjection,从此依赖注入模式成为实现组件间松耦合的主流设计思想。
3.1. 依赖注入的原理
那么应用了依赖注入,我们的开发模式将会发生什么样的变化呢?我们还是先来看看刚才的例子。下面的代码就是应用了依赖注入之后的储户Depositor类:
|
可以看到,这个Depositor类几乎就是最开始我们定义的那个最简单的、没有任何初始化依赖的过程的类!唯一不同的是在定义依赖成员变量的时候,多加了一个JavaSE5标准的注解——@In。这里@In注解是现今主流依赖注入框架之一JBoss
Seam所提供的一个注解,对于其它的依赖注入框架有着同样的使用方式,例如SpringFramework中提供了@Autowired注解等同于Seam的@In,Google
Guice框架中提供了@Inject注解等同于Seam的@In。关于依赖注入框架的话题我们稍候再做介绍,现在先来了解一下依赖注入框架的关于依赖注入的实现过程,这里我们还是以Seam框架为例进行介绍。
依赖注入框架的核心是依赖注入容器,也常被称为IoC容器或者叫Injector。其起的作用是管理一切注册到其中的依赖以及将这些依赖提供给请求依赖的依赖者。说到此或许有人会问,那这个依赖注入容器与前一节提到的ServiceLocator容器有什么不一样,不都是一个管理依赖对象的容器吗?答案是非常的不一样。不一样在于,首先依赖注入容器是极其轻量可控的,注册到其中的依赖对象可以方便的由开发者决定其标识符以及注册过程等,并且可以方便的放到单元测试环境中执行;其次依赖注入容器不仅仅是替开发者管理依赖,更重要的是它能够根据需要自动的去管理依赖对象的作用域及其生命周期,以及增强依赖对象的行为(即AOP),这一点我们在后面的章节中还会有详细的介绍。
回到刚才的例子:
|
这里被@In标注的地方被称作“注入点”(injectionpoint),声明注入点起到的作用就是,告诉依赖注入容器“在这里请把依赖对象给我!”,也就是@In向依赖注入容器发出了一个请求,之后容器会利用Java的反射机制将其保管的对象set到注入点,即完成了一次依赖注入。
如果@In注入点所请求的依赖对象自身还有依赖,那么依赖注入容器同样会以同样的方式先去设定好这个“依赖的依赖”,也就是说,依赖注入容器会帮助开发者构建一套完整的依赖关系图,最后将一个完全初始化好的依赖对象提供给依赖者。
严格地讲,依赖注入同样有很多种模式,当遇到诸如循环依赖模式、部分依赖模式等情况时,依赖注入容器并不能将“完全初始化”的对象提供给依赖者。这些情况比较特殊,各种依赖注入框架也有不同的解决方式,我们在此就不再详加讨论了。
至于如何将依赖注册到容器中,每种依赖注入框架都有不同的运用方式,但是基本上都是大同小异,这里我们看一段以Seam框架为例的代码:
|
这里@Name标注的类代表这个类需要作为依赖对象被注册到Seam容器中,在Seam容器随着应用程序启动过程中即可完成这个注册过程。之后注册到Seam容器的这两个依赖就可以在被请求的时候提供给依赖者了。Seam框架中除了@Name标注,还可以用XML文件的<component>标签配置的方式来声明一个需要被注册到容器中的组件类。而如果使用的是Spring框架,则可通过@Component或者XML的<bean>标签等方式来声明组件类;Guice框架中则是通过Module的binding等方式来完成这一过程,总而言之各种依赖注入框架都提供了方便的向其容器去注册依赖的方法。
需要注意的是,注解(如前面举例的@In)并不是定义注入点的唯一方式。一般依赖注入框架还会提供API的方式和XML配置的方式来声明注入点。例如API的方式中,使用Seam框架时调用其Component#getInstance的API,或者使用Spring框架时调用其BeanFactory#getBean的API,或者使用Guice时调用其Injector#
getInstance的API等,都是声明注入点的一种方法。再比如XML配置方式中,Seam和Spring框架都提供了<property>标签用于声明依赖者类中的注入点。
我们可以看到,应用了依赖注入设计思想之后,我们的Depositor类就可以以一种最简单的姿态出现在我们的代码库中。对于今后的维护,不管Bank和DepositBook两个依赖类发生了什么样的构造方法的变化,都不会影响到Depositor类本身。并且在单元测试中,我们可以方便的用Mock类替换掉实际的依赖。只需将Mock类绑定为相同的标识符,那么当依赖者请求依赖的时候,容器就会将Mock类提供给依赖者。例如:
|
依赖注入及AOP简述(三)——依赖注入的原理的更多相关文章
- 依赖注入及AOP简述(九)——单例和无状态Scope .
三.依赖注入对象的Scope及其生命周期 在前面的章节我们讲到,依赖注入容器之所以能够区别于以往的ServiceLocator等容器,是在于其不但能够自动构建多层次的.完整的依赖关系图,并且可以管理依 ...
- 依赖注入及AOP简述(五)——依赖注入的方式 .
二.依赖注入的应用模式 前面我们了解了依赖注入的基本概念,也对一些依赖注入框架进行了简单的介绍,这一章我们主要来讨论作为开发者如何利用依赖注入框架来实现依赖注入的设计思想. 1. 依赖注入的方 ...
- 依赖注入及AOP简述(七)——FQCN请求模式
2.2. FQCN请求模式 为了弥补纯字符串请求模式中的类型安全问题,全类名(FQCN)请求模式就应运而生了.其思想便是,在向容器请求依赖对象的时候,不是通过字符串的标识符.而是通过被请求的依赖 ...
- 依赖注入及AOP简述(六)——字符串请求模式 .
2. 依赖注入对象的请求模式 前一节我们讨论了关于声明注入点的几种方法,这一节主要来介绍在注入点上如何定位到所需要的标识符的话题.基本上,我们可以用字符串为标识符来请求依赖对象.或者用全类名( ...
- 依赖注入及AOP简述(一)——“依赖”的概念 .
一.入门:依赖注入 作为一种全新的设计模式理念,“依赖注入”这个词汇在软件设计开发中已经是越来越耳熟能详了,而各种流行于开源社区的“依赖注入框架”,也越来越多的被当作软件工程开发过程中使用的基础框架. ...
- 依赖注入及AOP简述(十一)——生命周期管理 .
2. 生命周期管理 各种依赖注入框架提供了替开发者管理各种Scope的便利功能,随之而来的就必然是被管理的依赖对象的生命周期管理的问题.所谓生命周期管理,就是一个对象在它所属的Scope中从被 ...
- 依赖注入及AOP简述(十三)——AOP应用举例(完结) .
2. AOP应用举例 在一般的应用程序开发中,有一些典型的AOP应用,使得开发者可以专注于业务逻辑本身,而不是与之完全无关的一些“方面”. l 首先就是关于前面介绍过的日志输出类 ...
- 依赖注入及AOP简述(十二)——依赖注入对象的行为增强(AOP) .
四.依赖注入对象的行为增强(AOP) 前面讲到,依赖注入框架的最鲜明的特点就是能够提供受容器管理的依赖对象,并且可以对对象提供行为增强(AOP)功能,所以这一章我们来讨论有关AOP的话题. 1. ...
- 依赖注入及AOP简述(十)——Web开发中常用Scope简介 .
1.2. Web开发中常用Scope简介 这里主要介绍基于Servlet的Web开发中常用的Scope. l 第一个比较常用的就是Application级Scope,通常我们会将一 ...
随机推荐
- Nginx日志文件配置与切割
Nginx日志的指令主要有两条: log_format,设置日志的格式 access_log,指定日志文件的存放路径.格式和缓存大小 两条指令在Nginx配置文件中的位置可以在http{……..}之间 ...
- hive优化之自己主动合并输出的小文件
1.先在hive-site.xml中设置小文件的标准. <property> <name>hive.merge.smallfiles.avgsize</name> ...
- 《你必须知道的495个C语言问题》知识笔记及补充
1. extern在函数声明中是什么意思? 它能够用作一种格式上的提示表明函数的定义可能在还有一个源文件里.但在 extern int f(); 和 int f(); 之间并没有实质的差别. 补充:e ...
- C++ 实现Trim
一.字符串去空格(没有处理字符串中间的空格) lTrim:除去字符串开头的空格 eg." abc123 " --> "abc123 " ...
- stagefright框架(六)-Audio Playback的流程
到目前为止,我们都只着重在video处理的部分,对于audio却只字未提.这篇文章将会开始audio处理的流程. Stagefright中关于audio的部分是交由AudioPlayer来处理,它是在 ...
- Andrord问题小结
问题描述:Gradle version 2.10 is required. Current version is 2.8.Gradle版本由2.8升为2.10后,发现所有依赖play-services ...
- V - stl 的 优先队列 Ⅱ
Description Because of the wrong status of the bicycle, Sempr begin to walk east to west every morni ...
- [原创]Windows下Google V8 javascript引擎编译
项目用到将v8嵌入到C++的情况,公司没时间研究,只有在家研究,编译过程一堆坑.记录一下. 网上百度的都是基于vs2010,或者早版本的v8编译,最新版本应该使用vs2013\vs2015.本文介绍的 ...
- c++ 资源索引
1.http://snippets.dzone.com/tag/c/ --数以千计的有用的C语言源代码片段 2.http://www.hotscripts.com/category/c-cpp/sc ...
- 一段简单c程序的汇编语言学习(ubuntu+x86)
c程序代码: #include <stdio.h> int main(void) { int i=0, j=0; for(i=0; i<8; i++) j=j+1; return 0 ...