您的位置:首页 > 编程语言 > Java开发

Java 动态代理

2012-01-09 15:31 218 查看
来源:http://www.cnblogs.com/kongxx/archive/2005/08/08/209749.html

在目前的Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。

其实现主要通过是java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。

Proxy类主要用来获取动态代理对象,InvocationHandler接口用来约束调用者实现,如下,HelloWorld接口定义的业务方法,HelloWorldImpl是HelloWorld接口的实现,HelloWorldHandler是InvocationHandler接口实现。代码如下:

业务接口:

package com.gq.annotation.proxy;

public interface HelloWorld {

void sayHelloWorld();
}
业务接口实现:
package com.gq.annotation.proxy;

public class HelloWorldImpl implements HelloWorld {

@Override
public void sayHelloWorld() {
System.out.println( "Hello World." );

}

}


InvocationHandler实现,需要在接口方法调用前后加入一部份处理工作,这里仅仅在方法调用前后向后台输出两句字符串,其代码如下:

package com.gq.annotation.proxy;

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

public class HelloWorldHandler implements InvocationHandler {

private Object source;

public HelloWorldHandler(HelloWorld source) {
this.source = source;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;

System.out.println( "Before invocation..." );
result = method.invoke( source, args );
System.out.println( "After invocation..." );

return result;
}

}
测试代码:
package com.gq.annotation.proxy;

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

public class Test {

/**
* @param args
*/
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();
}

}
Ø 首先获取一个业务接口的实现对象;

Ø 获取一个InvocationHandler实现,此处是HelloWorldHandler对象;

Ø 创建动态代理对象;

Ø 通过动态代理对象调用sayHelloWorld()方法,此时会在原始对象HelloWorldImpl. sayHelloWorld()方法前后输出两句字符串。

运行测试类输出如下:
Before invocation...
Hello World.
After invocation...
此处Test类中的方法调用代码比较多,在我们的实际应用中可以通过配置文件来来简化客户端的调用实现。另外也可以通过动态代理来实现简单的AOP。

-----------------------------------------------------------

-----------------------------------------------------------

来源:http://hi.baidu.com/malecu/blog/item/45d4952b31bc0e27d52af17a.html

java 动态代理深度学习,

一.相关类及其方法:

java.lang.reflect.Proxy,

Proxy 提供用于创建动态代理类和实例的静态方法.

newProxyInstance()

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序

(详见api文档)

java.lang.reflect.InvocationHandler,

InvocationHandler 是代理实例的调用处理程序 实现的接口。

invoke()

在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。

(详见api文档)

二.源代码:

被代理对象的接口及实现类:
package com.ml.test;

public interface Manager {
public void modify();
}
package com.ml.test;

public class ManagerImpl implements Manager {

@Override
public void modify() {
System.out.println("*******modify()方法被调用");
}
}
业务代理类:
package com.ml.test;

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

public class BusinessHandler implements InvocationHandler {

private Object object = null;

public BusinessHandler(Object object) {
this.object = object;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("do something before method");
Object ret = method.invoke(this.object, args);
System.out.println("do something after method");
return ret;

}
}
客户端类:
package com.ml.test;
import java.lang.reflect.Proxy;
public class Client {

public static void main(String[] args) {
// 元对象(被代理对象)
ManagerImpl managerImpl = new ManagerImpl();

// 业务代理类
BusinessHandler securityHandler = new BusinessHandler(managerImpl);

// 获得代理类($Proxy0 extends Proxy implements Manager)的实例.
Manager managerProxy = (Manager) Proxy.newProxyInstance(managerImpl
.getClass().getClassLoader(), managerImpl.getClass()
.getInterfaces(), securityHandler);

managerProxy.modify();
}
}
三.执行结果:

do something before method

*******modify()方法被调用

do something after method

四.机制分析:

Proxy.(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下几件事.

(1)根据参数loader和interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy.

$Proxy0类实现了interfaces的接口,并继承了Proxy类.

(2)实例化$Proxy0并在构造方法中把BusinessHandler传过去,接着$Proxy0调用父类Proxy的构造器,为h赋值,如下:

class Proxy{

InvocationHandler h=null;

protected Proxy(InvocationHandler h) {

this.h = h;

}

...

}

下面是本例的$Proxy0类的源码(好不容易才把它提出来):
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Manager {

private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;

static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);
m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}

public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}

@Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
.booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}

@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}

public final void modify() {
try {
super.h.invoke(this, m3, null);
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}

@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
接着把得到的$Proxy0实例强制转换成Manager.

当执行managerProxy.modify()方法时,就调用了$Proxy0类中的modify()方法.

在modify方法中,调用父类Proxy中的h的invoke()方法.

即InvocationHandler.invoke();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息