2.     依赖注入对象的请求模式

前一节我们讨论了关于声明注入点的几种方法,这一节主要来介绍在注入点上如何定位到所需要的标识符的话题。基本上,我们可以用字符串为标识符来请求依赖对象、或者用全类名(FQCN)为标识符来请求依赖对象、或者用两者混合的模式。下面我们来依次介绍。

2.1.    字符串请求模式

顾名思义,字符串请求模式即依赖注入框架将一个依赖绑定到指定的字符串上,而后将其装入依赖注入容器。依赖者通过这个字符串,向容器请求所需要的依赖。Seam和Spring都是典型的基于字符串请求模式的框架。

在这样的模式中,容器中管理的依赖的标识符是通过字符串来定义的,例如我们刚才定义Bank和DepositBook依赖的时候,就是分别将其绑定到了“bank”和“depositBook”这两个字符串上。

@Name("bank")  // 将BankICBC依赖绑定到"bank"

public class BankICBC implements Bank { // ……  }

@Name("depositBook")  // 将DepositBookICBC依赖绑定到"depositBook"

public class DepositBookICBC implements DepositBook { // ……  }

之后对于依赖者类,只要在注入点上声明需要请求标识符字符串为“bank”或“depositBook”的依赖,容器就会自动将BankICBC和DepositBookICBC的实例返回给依赖者了。注意前面我们也提到了,Seam框架中在@In注入点缺省是被认为请求与成员变量名同名的依赖,因此下面两种请求依赖的写法是一样的:

@In // 请求标识符为"bank"的依赖对象

private Bank bank;

@In // 请求标识符为"depositBook "的依赖对象

private DepositBook depositBook;

@In("bank") // 请求标识符为"bank"的依赖对象

private Bank bank;

@In("depositBook") // 请求标识符为"depositBook "的依赖对象

private DepositBook depositBook;

尽管Seam和Spring都采用了纯字符串的标识符定义的模式,但这种模式下有一个很大的弱点:违反了“类型安全(type-safe)”原则,也就是说可能会误将一个本不是依赖者类所希望的依赖对象注入进来。试想这样的场景:假设开发者在开发Depositor类并定义其所需要的依赖的时候,误将“bank”写成了“bak”,而其他开发者又恰好向容器中注册了一个标识符为“bak”的依赖。

@In("bak") // 错误地请求了标识符为"bak"的依赖对象

private Bank bank;

@Name("bak ")  // 其他开发者恰好向容器中注册了一个"bak"依赖

public class Bak { // …… 
}

此时Java编译器编译器是不会有任何错误信息提示的,因为@In是一个运行时注解,根据Java5的注解原理,运行时注解在编译时几乎就相当于一个注释行被编译器忽略掉了,只有到了运行时才会由解析它的代码段产生作用。因此无论是开发者定义成@In(“bak”)还是@In(“bakxxx”)等等,都不会对代码的编译造成任何影响。在这个例子中,虽然开发人员误将“bak”依赖请求进来,但会正常编译出应用程序,然后在运行这个应用程序的时候则会抛出ClassCastException的异常,这是就需要开发者花力气去排查错误了。

当然如果情况比较简单的话或许可以很快地排查掉这个bug,但是还有比这更可怕的事情:试想假设Bak类与Bank类是有继承关系的父子类,那么即使是在运行时也不会抛出ClassCastException的异常,因为依赖可以正确地被cast后set到注入点,这就有可能使得应用程序在被执行了很深之后才出现意想不到的bug,此时再去排查错误就会变得很困难了。

当然还有另外一种情况,就是如果容器中没有“bak”这个依赖的情况。此时声明注入点处的代码如果没有特殊限定,容器很可能将一个null对象设定到注入点,依然只会在运行时抛出NullPointerException异常。NPE异常或许是Java开发者最不愿意看到的异常了,因为它自描述性差,使得开发者经常很难定位错误所在。

依赖注入及AOP简述(六)——字符串请求模式 .的更多相关文章

  1. 依赖注入及AOP简述(七)——FQCN请求模式

    2.2.    FQCN请求模式 为了弥补纯字符串请求模式中的类型安全问题,全类名(FQCN)请求模式就应运而生了.其思想便是,在向容器请求依赖对象的时候,不是通过字符串的标识符.而是通过被请求的依赖 ...

  2. 依赖注入及AOP简述(八)——混合请求模式 .

    2.3.    混合请求模式 上一节讲到了FQCN(全类名)请求模式会带来依赖定义的柔软性较差的问题,因此字符串和全类名混合的模式又应运而生了.比如刚才的Spring中的API方式声明注入点的例子就可 ...

  3. 依赖注入及AOP简述(三)——依赖注入的原理

    3.     “依赖注入”登场 于是诸多优秀的IT工程师开始想出了更加轻量便利.更加具有可测试性和可维护性的设计模式——IoC模式.IoC,即Inversion of Control的缩写,中文里被称 ...

  4. 依赖注入及AOP简述(二)——工厂和ServiceLocator .

    2.2.    工厂模式 基于手工构建组件的诸多弱点,1995年“大师4人组”(GoF)在其经典著作<DesignPatterns>一书中提出了“工厂模式”,这种模式在一定程度上有效的解决 ...

  5. 依赖注入及AOP简述(五)——依赖注入的方式 .

    二.依赖注入的应用模式 前面我们了解了依赖注入的基本概念,也对一些依赖注入框架进行了简单的介绍,这一章我们主要来讨论作为开发者如何利用依赖注入框架来实现依赖注入的设计思想. 1.     依赖注入的方 ...

  6. 依赖注入及AOP简述(十三)——AOP应用举例(完结) .

    2.     AOP应用举例 在一般的应用程序开发中,有一些典型的AOP应用,使得开发者可以专注于业务逻辑本身,而不是与之完全无关的一些“方面”. l        首先就是关于前面介绍过的日志输出类 ...

  7. 依赖注入及AOP简述(十二)——依赖注入对象的行为增强(AOP) .

    四.依赖注入对象的行为增强(AOP) 前面讲到,依赖注入框架的最鲜明的特点就是能够提供受容器管理的依赖对象,并且可以对对象提供行为增强(AOP)功能,所以这一章我们来讨论有关AOP的话题. 1.    ...

  8. 依赖注入及AOP简述(九)——单例和无状态Scope .

    三.依赖注入对象的Scope及其生命周期 在前面的章节我们讲到,依赖注入容器之所以能够区别于以往的ServiceLocator等容器,是在于其不但能够自动构建多层次的.完整的依赖关系图,并且可以管理依 ...

  9. 依赖注入及AOP简述(四)——“好莱坞原则”和依赖注入框架简介 .

    3.2.    “好莱坞原则” 看了前面关于依赖注入概念的描述,我们来提炼出依赖注入的核心思想.如果说传统的组件间耦合方式,例如new.工厂模式等,是一种由开发者主动去构建依赖对象的话,那么依赖注入模 ...

随机推荐

  1. Vanya and Scales(思维)

    Vanya and Scales time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  2. Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8201936 在前文中,我们简要介绍了Andro ...

  3. 【剑指offer】Q40:数组中出现一次的数

    书里面关于分类的推断有些麻烦,通过某一位为0为1来对数组元素进行分类.假如第3位为1.那么也就是元素x & 8 等于或不等于0,所以不是必需非的用第几位去推断. def once(array) ...

  4. .Net 中DataSet导出为excel的方法

    依旧是留下代码防止以后忘记 protected void Export_Click(object sender, EventArgs e) { DataSet data = "" ...

  5. window服务创建

    第一步:创建服务 第二步:在Service1.cs视图中 右键 选择”添加安装程序” 这里要注意几个细节 设置上面的属性 这两个分别有属性,具体网上查使用方式 3 实例代码编写 主要下面几个方法 pr ...

  6. margin四个属性的顺序

    margin-top ,margin-right ,margin-bottom ,margin-left .方向为 上右下左,顺时针方向, 值可以是: 百分比(基于父对象总高度或宽度的百分比) 长度值 ...

  7. Javascript进阶篇——( 事件响应)笔记整理

    什么是事件 JavaScript 创建动态页面.事件是可以被 JavaScript 侦测到的行为. 网页中的每个元素都可以产生某些可以触发 JavaScript 函数或程序的事件. 鼠标单击事件(on ...

  8. iOS 获取系统目录

    //获取根目录 NSString *homePath = NSHomeDirectory(); NSLog(@"Home目录:%@",homePath); //获取Document ...

  9. Android系统五大布局详解Layout

    我们知道Android系统应用程序一般是由多个Activity组成,而这些Activity以视图的形式展现在我们面前, 视图都是由一个一个的组件构成的.组件就是我们常见的Button.TextEdit ...

  10. linux网络编程:select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET(转)

    从别人的博客中转载过来了这一篇文章,经过重新编辑排版之后展现于此,做一个知识点保存与学习. select函数用于在非阻塞中,当一个套接字或一组套接字有信号时通知你,系统提供select函数来实现多路复 ...