找回密码
 FreeOZ用户注册
查看: 1360|回复: 6
打印 上一主题 下一主题

[论坛技术] The Limitation of Proxy Design Pattern

[复制链接]
跳转到指定楼层
1#
发表于 5-11-2009 14:14:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
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.
回复  

使用道具 举报

2#
 楼主| 发表于 5-11-2009 16:39:55 | 只看该作者
Solution 1:

AntiProxy

1. AntiProxy Interface
  1. public interface AntiProxy {
  2.       public Object self();
  3.       public Class  getOrigClass();
  4. }
复制代码
2. AntiProxyHelper
  1. public class AntiProxyHelper {
  2.      public static Object invoke(Object obj, Method method, Object[] args){
  3.              Object result = null;
  4.              try{
  5.                  result = method.invoke(obj, args); return result;
  6.              }catch(Exception e){}
  7.             
  8.              if(method.getName().equals("self")) return obj;
  9.              else if(method.getName().equals("getOrigClass")) return obj.getClass();
  10.              throw new NoSuchMethodException(method.getName());
  11.      }
  12.      public static boolean instanceOf(Object obj, Class c){
  13.              if(c.isInstance(obj)) return true;
  14.              if(obj instanceof AntiProxy && c.isInstance(((AntiProxy)obj).self()) return true;
  15.              return false;
  16.      }
  17.      public static boolean isAntiProxyMethod(Method method) { return method.getDeclaringClass().equals(AntiProxy.class); }
  18. }
复制代码
3. newInstance
  1.     List<Class> ints = new LinkedList<Class>();
  2.     if(clazz.isInterface()) ints.add(clazz);    //clazz is the input Class object for proxy
  3.     else e.setSuperclass(clazz);

  4.     if(proxiedObject)                           //proxiedObject is the input object which is the target of the proxy calls. could be null
  5.         ints.add(AntiProxy.class);

  6.     if(!ints.isEmpty()) { Class[] cs = new Class[ints.size()]; ints.toArray(cs); e.setInterfaces(cs); }
  7.   
  8.     ....

  9.     return e.create();
复制代码
回复  

使用道具 举报

3#
 楼主| 发表于 5-11-2009 16:48:09 | 只看该作者

Solution 2

  1. boolean assigned = false;
  2. if(proxiedObject != null && clazz.isInstance(proxiedObject)){
  3.     //check if there is a constructor with no arguments
  4.   try{
  5.     Class c = proxiedObject.getClass(); Constructor con = c.getDeclaredConstructor();
  6.     int modifiers = con.getModifiers();
  7.     if(Modifier.isPrivate(modifiers)) throw new Exception();
  8.     assigned = true;
  9.   }catch(Exception e){
  10.     //do nothing
  11.   }

  12.   //set other interfaces or superclass accordingly
  13.   ...
复制代码
回复  

使用道具 举报

4#
发表于 6-11-2009 20:22:58 | 只看该作者
java不太熟悉,帮顶
回复  

使用道具 举报

5#
发表于 6-11-2009 21:55:21 | 只看该作者
用PROXY 创建出来的是MyClass 得代理,否则就不是PROXY模式了,当然你创建出来的新对象接口和MyClass 是一样的。.net中对proxy讲的应该讲的比较清楚了,java应该类似
回复  

使用道具 举报

6#
 楼主| 发表于 7-11-2009 09:31:45 | 只看该作者
你说得对,的确是这样。

对于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 发表
用PROXY 创建出来的是MyClass 得代理,否则就不是PROXY模式了,当然你创建出来的新对象接口和MyClass 是一样的。.net中对proxy讲的应该讲的比较清楚了,java应该类似
回复  

使用道具 举报

7#
发表于 6-12-2009 03:18:14 | 只看该作者
不太清楚搂主说的proxy 是不是proxy  pattern,

Proxy模式 的目的是调用实现同样接口的类,而调用者不需要考虑具体的实现,只要通过接口调用就可以。需要跨越某些边界的时候用到的, 比如数据,web service 等。那么创建的新类应该是基于MyInterface, 而不是MyClass的。
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+11, 2-11-2024 04:24 , Processed in 0.037444 second(s), 22 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表