The Limitation of Proxy Design Pattern
Assuming you have interfaces and classes as below:1. interface MyInterface
2. class MyClass implements MyInterface
Now create an Object obj based on MyClass using java.lang.reflect.Proxy or CGList.
Then run some code like:
if(obj instanceof MyClass)
return true;
else
return false;
You'll get false.
Why? Here is the code for object creation:
Enhancer e = new Enhancer();
e.setSuperclass(clazz); //clazz == MyInterface.class
e.setCallback(this);
return (T)e.create();
From the class hierarchy's point of view, the new object has nothing to do with MyClass. Solution 1:
AntiProxy
1. AntiProxy Interfacepublic interface AntiProxy {
public Object self();
public ClassgetOrigClass();
}2. AntiProxyHelperpublic class AntiProxyHelper {
public static Object invoke(Object obj, Method method, Object[] args){
Object result = null;
try{
result = method.invoke(obj, args); return result;
}catch(Exception e){}
if(method.getName().equals("self")) return obj;
else if(method.getName().equals("getOrigClass")) return obj.getClass();
throw new NoSuchMethodException(method.getName());
}
public static boolean instanceOf(Object obj, Class c){
if(c.isInstance(obj)) return true;
if(obj instanceof AntiProxy && c.isInstance(((AntiProxy)obj).self()) return true;
return false;
}
public static boolean isAntiProxyMethod(Method method) { return method.getDeclaringClass().equals(AntiProxy.class); }
}3. newInstance List<Class> ints = new LinkedList<Class>();
if(clazz.isInterface()) ints.add(clazz); //clazz is the input Class object for proxy
else e.setSuperclass(clazz);
if(proxiedObject) //proxiedObject is the input object which is the target of the proxy calls. could be null
ints.add(AntiProxy.class);
if(!ints.isEmpty()) { Class[] cs = new Class; ints.toArray(cs); e.setInterfaces(cs); }
....
return e.create();
Solution 2
boolean assigned = false;if(proxiedObject != null && clazz.isInstance(proxiedObject)){
//check if there is a constructor with no arguments
try{
Class c = proxiedObject.getClass(); Constructor con = c.getDeclaredConstructor();
int modifiers = con.getModifiers();
if(Modifier.isPrivate(modifiers)) throw new Exception();
assigned = true;
}catch(Exception e){
//do nothing
}
//set other interfaces or superclass accordingly
... java不太熟悉,帮顶 用PROXY 创建出来的是MyClass 得代理,否则就不是PROXY模式了,当然你创建出来的新对象接口和MyClass 是一样的。.net中对proxy讲的应该讲的比较清楚了,java应该类似 你说得对,的确是这样。
对于java.lang.reflect.Proxy我的了解并不是太多。我现在一直在用CGLIB,这东西功能强大,很容易做出:
1. Adapter模式
2. Proxy模式
现在java.lang.reflect.Proxy以及CGLIB的interceptor编程实现的模式,更接近Adapter模式,
因为没有强制地要求最终执行操作的必须为同一个interface的东西。
当然了,采用proxy.invoke()更方便,只不过不是强制的。
从Proxy模式的实质含义上看,它提供了一个接口剖面,让我们加入自己想处理的东西,这就是这几年提的AOP概念。
这个剖面的确很强大,以前需要能想象这个剖面的强大,但没有工具支持,自己很难简单实现这东西。reflect的出现,Proxy类的出现,CGLIB库的出现,让我们很容易实现这些功能。
现在的问题就是,我们如果只想在剖面中加入东西,加完后,这个东西还是原来的那个样子,应该怎样办?(Liskov Substitution Principle)。至少我们能有办法还原到原来的样子,又或者兼容原来的object。
可能你会问,既然程序员已经明知接下来就是Proxy到某个指定的接口或父类,就应该知道生出来的新对象的就只能是这样。你这样说很对,所以,我就说这个是Proxy模式的局限性。我现在的实际情况是:
1. 程序剖面只开在某个指定的类层次(或接口层次)(这个主要是因为Annotation的实现局限)
2. Proxy出来的对象,我希望对下一级的接口使用者透明。
如果我在每个interceptor实现时都追塑至Object这个level,程序的效率必然受影响。我要考虑的就是这个问题了。
原帖由 fishyoyo 于 6-11-2009 21:55 发表 http://www.freeoz.org/bbs/images/common/back.gif
用PROXY 创建出来的是MyClass 得代理,否则就不是PROXY模式了,当然你创建出来的新对象接口和MyClass 是一样的。.net中对proxy讲的应该讲的比较清楚了,java应该类似 不太清楚搂主说的proxy 是不是proxypattern,
Proxy模式 的目的是调用实现同样接口的类,而调用者不需要考虑具体的实现,只要通过接口调用就可以。需要跨越某些边界的时候用到的, 比如数据,web service 等。那么创建的新类应该是基于MyInterface, 而不是MyClass的。
页:
[1]