摘要:
大多数开发者都知道在运行时中如何装饰一个对象并向其增加额外的功能。四人帮(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;
}
}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_);
}
} 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");
public class anotherconcretedecorator extends adecorator {
public string doexecute(string in) {
system.out.println("anotherconcretedecorator: going to execute method : doexecute");
in = in + " modified by anotherconcretedecorator";
string ret = target.doexecute(in);
system.out.println("anotherconcretedecorator: after execute method : doexecute");
return ret;
}
}imybusinessobject aimybusinessobject = new mybusinessobject();
imybusinessobject wrappedobject =
new anotherconcretedecorator (new debugconcretedecorator(aimybusinessobject));
wrappedobject.doexecute("hello world");
public class mydebuginvocationhandler
implements java.lang.reflect.invocationhandler {
private object target = null;
public void settarget(object target_) {
this.target = target_;
}
public object invoke(object proxy, method method,
object[] args) throws throwable {
try {
system.out.println("going to execute method : " + method.getname);
object retobject = method.invoke(target, args);
system.out.println("after execute method : " + method.getname());
return retobject;
} catch(invocationtargetexception e) {
throw e.gettargetexception();
} catch(exception e) {
throw e;
}
}
}
imybusinessobject bo = new mybusinessobject();
mydebuginvocationhandler amydebuginvocationhandler =
new mydebuginvocationhandler();
amydebuginvocationhandler.settarget(bo);
imybusinessobject proxyobject =
(imybusinessobject) proxy.newproxyinstance
(imybusinessobject.class.getclassloader(),
new class[] { imybusinessobject.class },
amydebuginvocationhandler);
system.out.println(proxyobject.doexecute("hello world"));
myanotherinvocationhandler amyanotherinvocationhandler = new myanotherinvocationhandler ();
//here we will set the proxyobject, which we get through earlier
//code snippet, instead of the business object instance
amyanotherinvocationhandler.settarget(proxyobject);
imybusinessobject nextproxyobject =
(imybusinessobject) proxy.newproxyinstance
(imybusinessobject.class.getclassloader(),
new class[] { imybusinessobject.class },
amyanotherinvocationhandler);
system.out.println(nextproxyobject.doexecute("hello world"));
string[] interceptorclasses = {"mydebuginterceptor",
"myanotherinterceptor"};
imybusinessobject aimybusinessobject =
(imybusinessobject)myproxyfactory.getproxyobject
("mybusinessobject", interceptorclasses);
string ret = aimybusinessobject.doexecute("hello world"); public interface imethodinterceptor {
object interceptbefore(object proxy, method method,
object[] args, object realtarget);
void interceptafter(object proxy, method method,
object[] args, object realtarget, object retobject,
object interceptbeforereturnobject);
} public class mydebuginterceptor implements imethodinterceptor {
public object interceptbefore(object proxy, method method,
object[] args, object realtarget) {
system.out.println("mydebuginterceptor: going to execute method : ");
return null;
}
public void interceptafter(object proxy, method method, object[] args,
object realtarget, object retobject, object interceptbefore) {
system.out.println("mydebuginterceptor: after execute method : " );
}
} public class myanotherinterceptor implements imethodinterceptor {
public object interceptbefore(object proxy, method method,
object[] args, object realtarget) {
system.out.println("myanotherinterceptor: going to execute method : ");
if ( method.getname().equals("doexecute") &&
args != null && args.length >= 1 ) {
if ( args[0] instanceof string ) {
args[0] = args[0] +
" modified by myanotherinterceptor";
}
return null;
}
}
public void interceptafter(object proxy, method method, object[] args,
object realtarget, object retobject, object interceptbefore) {
system.out.println("myanotherinterceptor: after execute method : ");
}
} public class genericinvocationhandler
implements java.lang.reflect.invocationhandler {
private object target = null;
public void settarget(object target_) {
this.target = target_;
}
private object realtarget = null;
public void setrealtarget(object realtarget_) {
this.realtarget = realtarget_;
}
imethodinterceptor methodinterceptor = null;
public void setmethodinterceptor
(imethodinterceptor methodinterceptor_) {
this.methodinterceptor = methodinterceptor_;
}
public object invoke(object proxy, method method, object[] args)
throws throwable {
try {
object interceptbeforereturnobject = null;
if ( methodinterceptor != null ) {
interceptbeforereturnobject =
methodinterceptor.interceptbefore
(proxy, method, args, realtarget );
}
object retobject = method.invoke(target, args);
if ( methodinterceptor != null ) {
methodinterceptor.interceptafter
(proxy, method, args, realtarget,
retobject, interceptbeforereturnobject );
}
return retobject;
}
catch(invocationtargetexception e) {
throw e.gettargetexception();
}
catch(exception e) {
throw e;
}
}
}
public class myproxyfactory {
public static object getproxyobject( string classname,
string[] interceptors ) throws throwable {
object inputobject = gettargetobject(classname);
if ( interceptors != null && interceptors.length > 0 ) {
object inputproxiedobject = inputobject;
for ( int i=0; i < interceptors.length; i++ ) {
inputproxiedobject =
getproxyobject(inputobject, interceptors[i],
inputproxiedobject);
}
return inputproxiedobject;
}
else {
return inputobject;
}
}
private static object getproxyobject(object inobject,
string interceptor,object inproxiedobject) throws throwable {
genericinvocationhandler invocationhandler =
new genericinvocationhandler();
imethodinterceptor interceptorobject =
(imethodinterceptor)getinterceptor(interceptor);
if ( interceptor == null ) {
return inproxiedobject;
}
invocationhandler.settarget(inproxiedobject);
invocationhandler.setrealtarget(inobject);
invocationhandler.setmethodinterceptor(interceptorobject);
return proxy.newproxyinstance
(inobject.getclass().getclassloader(),
inobject.getclass().getinterfaces(),
invocationhandler) ;
}
private static object getinterceptor( string interceptors )
throws exception {
//...
//from the class name return the class instance.
//you can use class.forname and newinstance() method on class
//to return the object instance.
}
private static object gettargetobject( string classname )
throws exception {
//...
//from the class name return the class instance.
//you can use class.forname and newinstance() method on class
//to return the object instance.
}
} <security>
<businessclass>
<classname>mybusinessobject<classname>
<methodpermission>
<method>doexecute</method>
<validroles>admin,manager</validroles>
</methodpermission>
</businessclass>
</security>
public object interceptbefore(object proxy, method method,
object[] args, object realtarget) {
string nameofmethod = method.getname();
string targetclassname = realtarget.getclass().getname();
methodpermissions mperm =
securityfactory.getpermission(targetclassname);
if ( !mperm.isauthorized(mythreadlocalrolestore.getrole(),
nameofmethod ) ) {
throw new runtimeexception("user not authorized");
}
return null;
}
string[] interceptorclasses = {"mydebuginterceptor", "myanotherinterceptor"};
imybusinessobject aimybusinessobject =
(imybusinessobject)myproxyfactory.getproxyobject
("mybusinessobject", interceptorclasses);
string ret = aimybusinessobject.doexecute("hello world"); genericinvocationhandler代码:
public class genericinvocationhandler
implements java.lang.reflect.invocationhandler {
private object realtarget = null;
public void setrealtarget(object realtarget_) {
this.realtarget = realtarget_;
}
object[] methodinterceptors = null;
public void setmethodinterceptors
(object[] methodinterceptors_) {
this.methodinterceptors = methodinterceptors_;
}
public object invoke(object proxy, method method, object[] args)
throws throwable {
try {
object[] retinterceptbefore = null;
if ( methodinterceptors != null &&
methodinterceptors.length > 0 ) {
retinterceptbefore = new object[methodinterceptors.length];
for ( int i= methodinterceptors.length - 1; i >= 0; i-- ) {
if ( methodinterceptors[i] != null ) {
retinterceptbefore[i] =
((imethodinterceptor)methodinterceptors[i]).
interceptbefore(proxy,
method,args, realtarget );
}
}
}
object retobject = method.invoke(realtarget, args);
if ( methodinterceptors != null ) {
for ( int i= 0; i < methodinterceptors.length; i++ ) {
if ( methodinterceptors[i] != null ) {
((imethodinterceptor)methodinterceptors[i]).
interceptafter(proxy, method, args, realtarget,
retobject, retinterceptbefore[i] );
}
}
}
return retobject;
}
catch(invocationtargetexception e) {
throw e.gettargetexception();
}
catch(exception e) {
throw e;
}
}
}
public static object getproxyobject( string classname,
string[] interceptors ) throws throwable {
object inputobject = gettargetobject(classname);
if ( interceptors != null && interceptors.length > 0 ) {
return getproxyobject(inputobject, interceptors);
}
else {
return inputobject;
}
}
private static object getproxyobject(object inobject,
string[] interceptors) throws throwable {
genericinvocationhandler invocationhandler =
new genericinvocationhandler();
object[] interceptorobjects = getinterceptors(interceptors);
invocationhandler.setrealtarget(inobject);
invocationhandler.setmethodinterceptors(interceptorobjects);
return proxy.newproxyinstance
(inobject.getclass().getclassloader(),
inobject.getclass().getinterfaces(),
invocationhandler) ;
}
private static object[] getinterceptors(string[] interceptors)
throws exception {
object[] objinterceptors = new object[interceptors.length];
for ( int i=0; i < interceptors.length; i++ ) {
objinterceptors[i] = getinterceptor(interceptors[i]);
}
return objinterceptors;
}
synchronized(realtarget) {
retobject = method.invoke(target, args);
}string[] invocationhandlers = {"mydebuginvocationhandler",
"myanotherinvocationhandler"};
imybusinessobject aimybusinessobject =
(imybusinessobject)myproxyfactory.getproxyobject
("mybusinessobject", invocationhandlers);
string ret = aimybusinessobject.doexecute("hello world");public interface imyinvocationhandler {
void settarget(object target_);
void setrealtarget(object realtarget_);
}public abstract class amyinvocationhandler
implements imyinvocationhandler,
java.lang.reflect.invocationhandler {
protected object target = null;
protected object realtarget = null;
public void settarget(object target_) {
this.target = target_;
}
public void setrealtarget(object realtarget_) {
this.realtarget = realtarget_;
}
}
1. public class mydebuginvocationhandler extends amyinvocationhandler {
public object invoke(object proxy, method method, object[] args)
throws throwable {
try {
system.out.println("mydebuginterceptor: before execute method : "
+ method.getname());
object retobject = method.invoke(target, args);
system.out.println("mydebuginterceptor: after execute method : "
+ method.getname());
return retobject;
}
catch(invocationtargetexception e) {
throw e.gettargetexception();
}
catch(exception e) {
throw e;
}
}
} 2. public class myanotherinvocationhandler extends amyinvocationhandler {
public object invoke(object proxy, method method, object[] args)
throws throwable {
try {
system.out.println("myanotherinvocationhandler: before execute method : "
+ method.getname());
if ( method.getname().equals("doexecute")
&& args != null && args.length >= 1 ) {
if ( args[0] instanceof string ) {
args[0] = args[0] + " modified by myanotherinvocationhandler";
}
}
object retobject = method.invoke(target, args);
system.out.println("myanotherinvocationhandler: after execute method : "
+ method.getname());
return retobject;
}
catch(invocationtargetexception e) {
throw e.gettargetexception();
}
catch(exception e) {
throw e;
}
}
} public class mysynchronizeinvocationhandler extends amyinvocationhandler {
public object invoke(object proxy, method method, object[] args)
throws throwable {
object retobject = null;
synchronized(realtarget) {
retobject = method.invoke(target, args);
}
return retobject;
}
} public static object getproxyobject( string classname,
string[] invocationhandlers ) throws throwable {
object inputobject = gettargetobject(classname);
if ( invocationhandlers != null &&
invocationhandlers.length > 0 ) {
object inputproxiedobject = inputobject;
for ( int i=0; i < invocationhandlers.length; i++ ) {
amyinvocationhandler myinvocationhandler =
(amyinvocationhandler)getinvocationhandler
(invocationhandlers[i]);
inputproxiedobject = getproxyobject(inputobject,
myinvocationhandler, inputproxiedobject);
}
return inputproxiedobject;
}
else {
return inputobject;
}
}
public static object getproxyobject( object inputobject,
object[] invocationhandlers ) throws throwable {
if ( invocationhandlers != null
&& invocationhandlers.length > 0 ) {
object inputproxiedobject = inputobject;
for ( int i=0; i < invocationhandlers.length; i++ ) {
inputproxiedobject = getproxyobject(inputobject,
(amyinvocationhandler)invocationhandlers[i],
inputproxiedobject);
}
return inputproxiedobject;
}
else {
return inputobject;
}
}
private static object getproxyobject(object inobject,
amyinvocationhandler myinvocationhandler,
object inproxiedobject) throws throwable {
if ( myinvocationhandler == null ) {
return inproxiedobject;
}
myinvocationhandler.settarget(inproxiedobject);
myinvocationhandler.setrealtarget(inobject);
return proxy.newproxyinstance
(inobject.getclass().getclassloader(),
inobject.getclass().getinterfaces(),
myinvocationhandler) ;
}
public static object getproxyobject
( object inputobject, object[] invocationhandlers )
mydebuginvocationhandler dhandler = new mydebuginvocationhandler();
myanotherinvocationhandler ahandler = new myanotherinvocationhandler();
imybusinessobject bo = new mybusinessobject();
//now set any variables to these objects
//or some of these objects may be singletons
object[] invocationhandlers = { dhandler, ahandler };
(imybusinessobject)myproxyfactory.getproxyobject
(bo , invocationhandlers);
string ret = aimybusinessobject.doexecute("hello world");
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器