Java动态代理

众所周知,用JDK实现动态代理时,必需要有一个实现java.lang.reflect.InvocationHandler的实现类,但是我就这个实现类的
Object invoke(Object proxy, Method method, Object[] args) 方法,比较不能理解,为什么要把 proxy传入方法中,因为这个参数在很多时候我都没有使用到,而且也想不到,什么时候需要用proxy这个参数,帮忙回答一下.谢谢

8个回答

看看这篇,关于动态代理的原理,讲得很详细
Java 动态代理机制分析及扩展,第 1 部分

[url]http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html[/url]

Java 动态代理机制分析及扩展,第 2 部分

[url]http://www.ibm.com/developerworks/cn/java/j-lo-proxy2/index.html[/url]

Object invoke(Object proxy,Method method,Object[] args)throws Throwable
proxy - 在其上调用方法的代理实例
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null

应该先熟悉一下api说明

Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

参数:
[color=red]proxy - 在其上调用方法的代理实例[/color]
method - 对应于在代理实例上调用的接口方法的 Method 实例。Method 对象的声明类将是在其中声明方法的接口,该接口可以是代理类赖以继承方法的代理接口的超接口。
args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。
返回:
从代理实例的方法调用返回的值。如果接口方法的声明返回类型是基本类型,则此方法返回的值一定是相应基本包装对象类的实例;否则,它一定是可分配到声明返回类型的类型。如果此方法返回的值为 null 并且接口方法的返回类型是基本类型,则代理实例上的方法调用将抛出 NullPointerException。否则,如果此方法返回的值与上述接口方法的声明返回类型不兼容,则代理实例上的方法调用将抛出 ClassCastException。

这个proxy是用java动态代理生成的代理对象

例子代码:
[code="java"]

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;

public class DynamicProxyTest {
public static Object proxy;
public static void main(String[] args) {

    HelloWorld hw = new HelloWorldImpl();

    InvocationHandler handler = new HelloWorldHandler(hw);

    HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(hw.getClass()
            .getClassLoader(), hw.getClass().getInterfaces(), handler);
    proxy.sayHelloWorld();

    //判断是否生成的代理对象
    System.out.println(DynamicProxyTest.proxy == proxy);
}

}

class HelloWorldHandler implements InvocationHandler {
// 要代理的原始对象
private Object objOriginal;

/**
 * 构造函数。
 * 
 * @param obj
 *            要代理的原始对象。
 */
public HelloWorldHandler(Object obj) {
    this.objOriginal = obj;
}

public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {

    Object result;

    // 方法调用之前
    doBefore();

    //把这个proxy的引用保存在DynamicProxyTest.proxy,以便之后判断是否是生成的代理对象
    DynamicProxyTest.proxy = proxy;
    // 调用原始对象的方法
    result = method.invoke(this.objOriginal, args);

    // 方法调用之后
    doAfter();

    return result;
}

private void doBefore() {
    System.out.println("before method invoke!");
}

private void doAfter() {
    System.out.println("after method invoke!");
}

}

class HelloWorldImpl implements HelloWorld {
public void sayHelloWorld() {
System.out.println("Hello World!");
}
}

interface HelloWorld {
void sayHelloWorld();
}

[/code]

[url=http://www.iteye.com/topic/57004]http://www.iteye.com/topic/57004[/url] 这里谈论过~可以看看!
要弄懂其中原理,先跟我一起看看代理模式吧:(认真阅读下面下)
代理模式解决[color=green]不同请求[/color]和[color=blue]相应的目标对象[/color]的[color=red]中介作用[/color],实现面向接口编程,封装对象的行为实现 ;
Java API中提供了对Proxy模式的支持,主要是通过反射(Reflect)包中的Proxy类和InvocationHandler接口实现,具体过程如下:

1) 实现InvocationHandler接口,在invoke()方法中[color=blue]实现代理类要完成的操作[/color];

(2) 通过[code="java"]Proxy.newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)[/code]方法生成一个代理类,从参数可以看出代理类将[color=red]实现被代理对象的接口[/color],而[color=blue]具体的实现过程[/color]是在上面实现的[color=indigo]InvocationHandler.invoke()[/color]中定义的.

为了减少篇幅,实例参看
[url=http://zhangljerry.iteye.com/blog/132927]http://zhangljerry.iteye.com/blog/132927[/url]

更详细的代理模式(查看例子请链接到网站,这个网页的例子也很有个性)
[url=http://blog.csdn.net/wdwgr/archive/2009/04/09/4060739.aspx]http://blog.csdn.net/wdwgr/archive/2009/04/09/4060739.aspx[/url]
二. 代理模式所涉及到的角色:

抽象角色:提供一种真实角色和代理角色所共有的接口
真实角色:定义了代理角色要代理的真实对象
代理角色:含有对真实角色的引用,[color=darkblue]通常在客户端调用时代理对象都要在真实角色对象的基础上增加一些真实角色所不能胜任的工作,而不只是简单的含有真实角色的引用[/color]

三. 举例:

跟MM在网上聊天,一开头通常总是“hi”,“你好”, “你从哪里来?”, “你多大了”,等等这些话,真烦人,写个程序为我做代理吧,凡是收到这些消息,都设置好了自动回复功能,接收到其他有价值的消息时在通知我回答,怎么样,很酷吧,这都要归功于这个代理类。

Basically, methods inherited from java.lang.Object is not implemented by proxy object. (weird right? proxy object is created by a native method whose source code has not been released to public by Sun.)

You can try to call toString(), hashCode() or equals() methods of proxy object , and it should raise an java.lang.NullPointerException.

By this case , you will need the proxy object in invoke() to override above methods.

Object invoke(Object proxy, Method method, Object[] args)

第一个是你想invoke谁的方法

也就是说第一个参数就是要执行这个方法的对象

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问