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

三、依赖注入对象的Scope及其生命周期

在前面的章节我们讲到,依赖注入容器之所以能够区别于以往的ServiceLocator等容器,是在于其不但能够自动构建多层次的、完整的依赖关系图,并且可以管理依赖对象的Scope和对其进行行为增强。有关行为增强的话题我们会在下一章介绍,这里我们先来看看有关依赖对象的Scope及其生命周期管理的话题。

1.     依赖注入对象的Scope

Scope,即作用域,是指面向对象开发中所设计的某一类对象的生存期间。我们先从普通Java程序开发中最常用的单例和无状态两种Scope入手,之后再来讨论Web应用程序开发中几种常见的Scope。

1.1.    单例和无状态Scope

无状态Scope是最简单、生存期间最短的一种Scope,我们所有通过new出来的非静态对象都属于这种Scope,它随着使用这个对象的对象(可能是依赖者类,也可能是依赖者类里的一个方法)的消亡而消亡。反之,单例则是生存期间最长的一种Scope,它以静态的模式生存在JVM的“旧年代区域”,永远不会被JVM回收。比如我们肯定都写过或使用过类似这样的单例模式:

public class BankICBC implements Bank {

private static Bank bankICBC; // bankICBC为一个静态单例

private BankICBC() {} // 私有构造方法,使得外界无法直接new出其对象

public static Bank Instance() {

return null == bankICBC ? new BankICBC() : bankICBC; // 创建一个单例对象

}

// ……

}

还用我们取款的例子来说,假设这个储户用的存折类型是定期存单,取款之后银行要收回定期存单,这种情况下对于每一次取款的存折依赖来说,它都是一个无状态的,也就是说每次取款都需要一个新的存折,因此这个时候存折就是一个无状态的依赖。我们再假设这个储户附近只有一所银行,也就是说不管什么时候去取款都会去同一所银行,此时银行就是一个单例的依赖,每次执行withDraw方法是都是使用的同一个银行依赖对象。

在依赖注入框架之前,我们对于无状态的存折依赖和单例的银行依赖的创建,可能会分别使用new和静态的方式。new方式的诸多问题我们已经在第一章讨论过了。而静态的方式同样有着开发者负担管理JVM全局变量的不便或是易造成内存泄漏等诸多问题。依赖注入框架可以帮助开发者管理这些Scope的依赖,使得开发者获取不同Scope的依赖对象变得非常简单并且不需要自己去维护它。

下面我们以Seam框架为例说明如何定义这两种Scope。Spring、Guice框架也具有极为类似的定义方式,就不再具体举例了。

@Name("bank")

@Scope(ScopeType.APPLICATION) // 声明为单例Scope

public class BankICBC implements
Bank { // ……  }

@Name("depositBook")

@Scope(ScopeType.STATELESS) // 声明为无状态Scope

public class DepositBookICBC
implements DepositBook { // …… 
}

注意在依赖注入框架中,所谓“单例”并不是传统意义上的单例,它不是JVM中唯一存在的一个静态变量,而是以依赖注入容器(Injector)为单位唯一存在的非静态变量,从而避免了过多占用JVM的旧年代区域的内存等问题。

时间: 2024-11-08 21:30:10

依赖注入及AOP简述(九)——单例和无状态Scope .的相关文章

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

3.     “依赖注入”登场 于是诸多优秀的IT工程师开始想出了更加轻量便利.更加具有可测试性和可维护性的设计模式——IoC模式.IoC,即Inversion of Control的缩写,中文里被称作“控制反转”.至于为什么会有这么一个看似古怪的名字,我们稍后会做解释.2004年著名软件工程学者和工程师Martin Fowler在其论文<Inversion ofControl Containers and the Dependency Injection pattern>中将IoC更名为De

依赖注入及AOP简述(十)——Web开发中常用Scope简介 .

1.2.    Web开发中常用Scope简介 这里主要介绍基于Servlet的Web开发中常用的Scope. l        第一个比较常用的就是Application级Scope,通常我们会将一些贯穿整个EAR都会用到的常量定义.通用的服务组件.类似DBConnection连接创建等比较消耗资源的组件等等放到这个Scope中去.Application级Scope是与应用程序的ServletContext共存亡的,因此可以理解为所部署应用程序的ServletContext中的“单例Scope

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

四.依赖注入对象的行为增强(AOP) 前面讲到,依赖注入框架的最鲜明的特点就是能够提供受容器管理的依赖对象,并且可以对对象提供行为增强(AOP)功能,所以这一章我们来讨论有关AOP的话题. 1.     对依赖对象进行行为增强 所谓AOP,就是Aspect Oriented Programming(面向方面的编程),核心思想是把一个“方面”独立出来,从而实现组件间的松耦合.也许有些晦涩难懂,所以我们还是看个简单的例子. 在我们的银行依赖中,假设有个需求,即在每一笔取款业务的前后都要输出日志信息.

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

二.依赖注入的应用模式 前面我们了解了依赖注入的基本概念,也对一些依赖注入框架进行了简单的介绍,这一章我们主要来讨论作为开发者如何利用依赖注入框架来实现依赖注入的设计思想. 1.     依赖注入的方式 前面我们提到,所谓“依赖”,最简单地去解释就是一个Java类里的成员变量.我们都知道,给一个类中的私有成员变量赋值的方法通常有:通过Constructor构造方法.通过Setter方法.通过反射机制将私有变量的可见性设为true这三种方法.同样道理,依赖注入框架也是利用这三种方式来完成依赖对象的

依赖注入及AOP简述(一)——“依赖”的概念 .

一.入门:依赖注入 作为一种全新的设计模式理念,“依赖注入”这个词汇在软件设计开发中已经是越来越耳熟能详了,而各种流行于开源社区的“依赖注入框架”,也越来越多的被当作软件工程开发过程中使用的基础框架.这一章我们主要介绍什么是依赖注入.它的来源是什么.以及能给我们带来什么样的好处. 1.     “依赖”的概念 要了解依赖注入,我们首先需要了解什么是“依赖”.从现实世界的观点来看,“依赖”即某个实体对象为了完成某项功能,必须要依托另外一些实体对象,那么这些被依托的实体对象即被称为“依赖”(Depe

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

2.     AOP应用举例 在一般的应用程序开发中,有一些典型的AOP应用,使得开发者可以专注于业务逻辑本身,而不是与之完全无关的一些“方面”. l        首先就是关于前面介绍过的日志输出类的功能,当然前面的例子非常简单,实际上要输出的日志信息中往往有很多的可变参数,这时就需要从被拦截对象的上下文中取出相应的信息进行行为的增强. l        最常用的AOP应用就是关于DB事务的管理了.业务处理成功则向DB提交事务,反之则回滚事务——这是每一个开发者都会写过的代码.但是实际上这种事

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

3.2.    “好莱坞原则” 看了前面关于依赖注入概念的描述,我们来提炼出依赖注入的核心思想.如果说传统的组件间耦合方式,例如new.工厂模式等,是一种由开发者主动去构建依赖对象的话,那么依赖注入模式则是其反向的,即被动地等待别人做好一个依赖对象提供给我. 在美国好莱坞众多电影工厂在寻找演员的时候通常奉行着这么一个原则:不要找我,需要的时候我去找你(“Don’tcall us; we’ll call you!”),把相同的思路运用到我们的软件工程里通常也被称作“好莱坞原则”(Hollywood

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

2.2.    FQCN请求模式 为了弥补纯字符串请求模式中的类型安全问题,全类名(FQCN)请求模式就应运而生了.其思想便是,在向容器请求依赖对象的时候,不是通过字符串的标识符.而是通过被请求的依赖的全类名来定位依赖.这样如果开发者误将全类名标识符写错的话,在编译时立即会提醒“类不存在”.并且,如果使用Eclipse等IDE开发工具的话,用其提供的自动完整代码的功能就会轻松地将依赖的全类名标识符定义到代码中. 在第一章的“3.3 依赖注入框架简介”一节中我们提到了Google Guice框架是

依赖注入及AOP简述(十一)——生命周期管理 .

2.     生命周期管理 各种依赖注入框架提供了替开发者管理各种Scope的便利功能,随之而来的就必然是被管理的依赖对象的生命周期管理的问题.所谓生命周期管理,就是一个对象在它所属的Scope中从被容器创建开始.到被提供给依赖者.再到最后的消亡这一整个过程中,依赖注入框架提供了一系列的回调方法的接口,使框架自身以及开发者都可以利用这些接口对各个生存时点的依赖对象做一些操作和管理等. 例如依赖注入容器在创建一个依赖对象的时候,远不是new一个对象那么简单,而是一个极其复杂地Wrap这个对象的过程