|
摘要: 大多数开发者都知道在运行时中如何装饰一个对象并向其增加额外的功能。四人帮(GoF)的装饰器模式可帮助开发者获得这个功能。在反射包中,J2SE 1.3引入动态代理用于动态地装饰一个业务对象。此外,链化动态代理可以在运行时动态地向一个业务对象增加多种行为。特别地,这些额外的行为的类型是由面向方面编程定位的。这篇文章并不打算对AOP作深入的讨论,而准备把重点放在动态代理的一般链化上,从而使开发者可以用以框架驱动的方法去实现一些AOP概念。如果一个项目早已使用用某些现存的AOP框架,那么开发者不用再担心实现一个定制的框架。开发者不论何种原因,在他们的项目中不使用这个框架仍然可以以一种有效的方法中且用较小的努力就可获得链化动态代理的好处。
今天,用简单Java对像(POJOs)编程是相当流行的。当我们用POJOs编程时,人们可以相当容易地应用面向对象编程方法(OOP)。但有时在一个项目中用OOP去实现横切面(cross-cutting aspects)被证明是很困难的。例如,通常地,对于某个项目,在一个POJOs的业务对象中用OOP去实现日志或安全功能是很因难的。在J2SE1.3中引入的动态代理提供了一种方便的解决方法。
动态代理的背后思想是在一个对象的周围插入动态的行为但不改变对象的已有代码和接口。著名的四人邦的装饰器模式提供一种不必改变对象代码就可以装饰一个对象(改变它的行为)并向其增加横切面的方法。现在的许多框架和工具都使用这个模式。但当实现静态的装饰时会导致一些问题,在这篇文章的后面我会对此进行讨论。
之前引入的动态代理是没有直接的办法用于动态地装饰一个对象的。于是供应商们提供一些会自动产生代码去装饰对象的工具。尽管代码生成工具可以帮助我们产生静态的装饰器,但它要求一些额外的步骤,同时还带来对生产代码的维护开销。通过使用动态代理,我们可以大大的减少自动生成的代码量(甚至可能是零)。
为了理解动态代理是如何工作的,同时看一下动态代理在它的位置上能起什么作用。让我们举一个装饰器类将作为一个方法拦截器的例子。如果像这样使用动态代理,我们可能就面临某些编程的复杂性。在这篇文章的后面,你将会看到如何包装和动态代理有关的复杂性,并在它们之上提供一个抽象,在这篇文章中所在使用的大多数源代码都可以从Resources下载。
版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接 作者:Srijeeb Roy;EsunYang(作者的blog:http://blog.matrix.org.cn/page/EsunYang) 原文:http://www.matrix.org.cn/resource/article/44/44408_ Dynamic+Proxy+AOP.html 关键字:Dynamic;AOP;Proxy
没有动态代理的静态装饰和链化
假设我们有一个简单的业务接口: public interface IMyBusinessObject { public String doExecute(String in); }
这个接口有一个业务对象类的实现。public class MyBusinessObject implements IMyBusinessObject { public String doExecute(String in) { System.out.println("Here in MyBusinessObject doExecute: input :" + in); return in; } }
现在,我们想在doExecute()方法之前和之后增加一些行为(如logging)。装饰器模式使我们十分容易增加这个功能。public abstract class ADecorator implements IMyBusinessObject { protected IMyBusinessObject target; public void setTarget(IMyBusinessObject target_) { this.target = target_; } public ADecorator(){} public ADecorator(IMyBusinessObject target_) { setTarget(target_); } }
现在定义一个从ADedorator扩展来的具体类DebugConcreteDecorator,我们的目的是在我们业务对象被调用之前和之后加入一些调试信息:public class DebugConcreteDecorator extends ADecorator { public String doExecute(String in) { System.out.println("DebugConcreteDecorator: before method : doExecute ");
String ret = target.doExecute(in); System.out.println("DebugConcreteDecorator: after method : doExecute "); return ret; } }
现在在客户端,我们调用业务对象:IMyBusinessObject aIMyBusinessObject = new MyBusinessObject(); IMyBusinessObject wrappedObject = new DebugConcreteDecorator(aIMyBusinessObject); wrappedObject.doExecute("Hello World");
在上面的代码片段中,我们用DebugConcreteDecorator类实例包装了我们的业务对象。因为DebugConcreteDecorator是从ADecorator类中扩展来的,并且ADecorator实现了业务对象接口IMyBusinessObject,因此DebugConcreteDecorator类本身就是接口IMyBusinessObject的实例。首先,我们创建一个MyBusinessObject实例,然后,我再创建DebugConcreteDecorator实例并在构造函数中向其传递业务对象。因为在DebugConcreteDecorator中是没有构造函数,所以它的超类(ADecorator)的构造函数会被调用,并目标对象设定为MyBusinessObject的实例。于是,当DebugConcreteDecorator实例的doExectute()被调用时,它首先记录一些调式信息(使用System.out)然后调用实际业务对象上(MyBusinessObject)的业务方法。
1
2
3
4
5
6
7
下一页>>
|