锁定老帖子 主题:Java动态代理的设计是否有缺陷??
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-04-25
xyz20003 写道 ^_^个人感觉这个api没问题呀,如果没有Object proxy这第一个参数,当我们希望在代理方法中访问proxy的时候该怎么办呢?
最简单的场景就像我之前举出的, public class Hello { public Hello doSomething() { return this; } } 如果不提供Object proxy这个第一个参数,我们就不容易获得proxy了,手里最多只有一个target可以用。 如果参与讨论的各位大侠有时间,不妨考虑一下这种情况吧。多谢。 呵呵,又碰到你了。 获得proxy有什么用??这一直是我的疑问。 这个例子,我还是看不出与proxy有什么关系?(我有点愚钝了O(∩_∩)O~)。劳烦您指教!! |
|
返回顶楼 | |
发表时间:2010-04-25
只是想讨论一下,像我举的例子,方法的返回值是实例本身,如果invoke方法中没有Object proxy的话,你该如何处理呢?
|
|
返回顶楼 | |
发表时间:2010-04-25
xyz20003 写道 只是想讨论一下,像我举的例子,方法的返回值是实例本身,如果invoke方法中没有Object proxy的话,你该如何处理呢? method.invoke(Object obj , Object[] args)方法返回的值,不就是那个方法返回的值吗? |
|
返回顶楼 | |
发表时间:2010-04-25
我能理解你们吵了半天,所以比较晕,所以我详细的把自己的思路整理一下,咱们慢慢研究。
首先,我有一个接口 pubic interface Hello { Hello preparePrefix(String prefix); Hello prepareName(String name); String getResult(); } 下面我想用proxy来代理这个接口,实现下面的功能 Hello hello = Proxy... hello.preparePrefix("Hello").prepareName("Lingo").getResult(); 请问,如果不借助Object proxy这个参数,你该如何实现呢? |
|
返回顶楼 | |
发表时间:2010-04-25
最后修改:2010-04-25
用了Object proxy这个参数,我就可以这么实现。
public interface Hello { Hello preparePrefix(String prefix); Hello prepareName(String name); String getResult(); } import java.lang.reflect.*; public class Test { public static void main(String[] args) { Hello hello = (Hello) Proxy.newProxyInstance( Hello.class.getClassLoader(), new Class[] { Hello.class }, new HelloHandler()); String result = hello.preparePrefix("Hello") .prepareName("Lingo") .getResult(); System.out.println(result); } public static class HelloHandler implements InvocationHandler { private String prefix; private String name; public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("preparePrefix")) { prefix = (String) args[0]; return proxy; } else if (method.getName().equals("prepareName")) { name = (String) args[0]; return proxy; } else if (method.getName().equals("getResult")) { return prefix + " " + name; } return null; } } } |
|
返回顶楼 | |
发表时间:2010-04-25
package proxy.study.oo; public interface Hello { Hello preparePrefix(String prefix); Hello prepareName(String name); String getResult(); }
package proxy.study.oo; public class HelloImpl implements Hello { private String name; private String prefix; @Override public String getResult() { return name + " : " + prefix; } @Override public Hello prepareName(String name) { this.name = name; return this; } @Override public Hello preparePrefix(String prefix) { this.prefix = prefix; return this; } } package proxy.study.oo; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; public void setTarget(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; result = method.invoke(target, args); return result; } } package proxy.study.oo; import java.lang.reflect.Proxy; public class ProxyDemo { public static void main(String[] args) { HelloImpl real = new HelloImpl(); MyInvocationHandler handler = new MyInvocationHandler(); handler.setTarget(real); Hello proxyObject = (Hello) Proxy .newProxyInstance(real.getClass().getClassLoader(), new Class[] { Hello.class }, handler); String result = proxyObject.preparePrefix("Hello").prepareName("Lingo").getResult(); System.out.println("执行的结果:" + result); } } 输出: 执行的结果:Lingo : Hello
|
|
返回顶楼 | |
发表时间:2010-04-25
你可以和我的实现比较一下,我的实现可以保证用户一直使用的都是proxy,你的实现从第一次方法调用之后,就把被代理的实例暴露给客户了。
这样的问题是,如果我的代理中还要进行日志,权限,事务等拦截,你的这种方式就会造成后续的拦截失效。 |
|
返回顶楼 | |
发表时间:2010-04-25
xyz20003 写道 用了Object proxy这个参数,我就可以这么实现。
在你的实现中,你感觉到没有。你的InvocationHandler是和某个接口紧密相连的。 切面有可能是面对多个接口的,那么你又应该怎么做? 很谢谢你一直在回复。PS:我们不是在吵,呵呵,是在讨论话题。 |
|
返回顶楼 | |
发表时间:2010-04-25
xyz20003 写道 你可以和我的实现比较一下,我的实现可以保证用户一直使用的都是proxy,你的实现从第一次方法调用之后,就把被代理的实例暴露给客户了。
这样的问题是,如果我的代理中还要进行日志,权限,事务等拦截,你的这种方式就会造成后续的拦截失效。 这是可以通过chain(串接的方式实现的)。即,将前一个的proxyObject作为realObject传入到后一个InvocationHandler中去。 参见这篇文章: Generically chain dynamic proxies http://www.javaworld.com/javaworld/jw-01-2006/jw-0130-proxy.html |
|
返回顶楼 | |
发表时间:2010-04-25
呵呵~看来你没看懂我所说的问题呀。
我的代码里 Hello hello(其实是proxy) hello.preparePrefix("Hello")(返回的还是proxy) .prepareName("Lingo")(返回的还是proxy) .getResult(); 你的代码里 Hello hello(其实是proxy) hello.preparePrefix("Hello")(从这里开始,返回的都是target) .prepareName("Lingo")(下面都是在直接操作target,proxy已经失效) .getResult(); 你说的我绑定在一个接口上,说的正式一点儿应该是:我列举的场景stateful,而平常经常遇到的场景都是stateless,所以你会感到有些不适应。 至于你说的chain,似乎和咱们说的没什么关联,你先仔细考虑一下,思维不要跳的太快,先把我说的问题想明白。:) |
|
返回顶楼 | |