一、代理简要介绍:
java中的代理有两种:静态代理和动态代理
静态代理:程序员自己生成代理类,编译代码之后,代理类随之生成,程序运行时,代理类已经是确定了,灵活性低。
动态代理:不需要程序员自己编写,代理类字节码由程序在运行过程中动态生成,是的原始类和代理类之间没有了直接联系,灵活性很高。
二、代理实例
java中实现动态代理可以使用jdk自带的实现,也可以通过工具实现,如CGLIB技术,本文主要介绍jdk动态代理。
jdk的动态代理是基于接口的,要代理一个类,原始类必须实现接口,接口可以有多个。
JDK动态代理中包含一个类和一个接口:
InvocationHandler接口:
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
参数说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
(1)定义一个接口:
package com.my.proxy;
public interface IHelloWorld {
public void sayHi();
}
package com.my.proxy;
public class HelloWorldImpl implements IHelloWorld {
@Override
public void sayHi() {
// TODO Auto-generated method stub
System.out.println("hello world");
}
}
package com.my.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @ClassName: HelloWorldProxy
* @Description: TODO
* @author yangjun 118
* @date 2013-4-18 下午4:21:00
*
*/
public class HelloWorldProxy implements InvocationHandler {
private Object target;
/**
* @Description: 绑定被代理的对象,返回对应的代理类,可以转化为被代理类实现的某个接口
* @param target 具体的被代理类的实现类
* @return Object 代理类
* @throws
*/
public Object bind(Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("before hello world");
Object result = null;
method.invoke(target, args);
System.out.println("after hello world");
return result;
}
}
package com.my.proxy;
public class TestHelloWorldProxy {
public static void main(String []args) {
//动态代理的字节码是用sun.misc.ProxyGenerator.generateProxyClass(arg0, arg1)方法生成的
//加入如下配置,可以在工程目录下生成名为$Proxy0.class代理类,利用反编译工具可以清晰看到编译之后的代理类字节码
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
HelloWorldProxy hproxy = new HelloWorldProxy();
IHelloWorld ihw = (IHelloWorld)hproxy.bind(new HelloWorldImpl());
ihw.sayHi();
}
}
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space
import com.my.proxy.IHelloWorld;
import java.lang.reflect.*;
public final class $Proxy0 extends Proxy
implements IHelloWorld
{
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;
public $Proxy0(InvocationHandler invocationhandler)
{
super(invocationhandler);
}
public final boolean equals(Object obj)
{
try
{
return ((Boolean)super.h.invoke(this, m1, new Object[] {
obj
})).booleanValue();
}
catch (Error ) { }
catch (Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final void sayHi() { try { super.h.invoke(this, m3, null); return; } catch (Error ) { } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } }
public final int hashCode()
{
try
{
return ((Integer)super.h.invoke(this, m0, null)).intValue();
}
catch (Error ) { }
catch (Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString()
{
try
{
return (String)super.h.invoke(this, m2, null);
}
catch (Error ) { }
catch (Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
Class.forName("java.lang.Object")
});
m3 = Class.forName("com.my.proxy.IHelloWorld").getMethod("sayHi", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", 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());
}
}
}
从生成代理类$Proxy0.class中可以看出,代理是是继承了Proxy类,实现了IHelloWorld接口,可以将动态代理看做是一个实现了IHelloWorld接口的的实例调用了IHelloWorld接口的sayHi()方法。在代理类的sayHi()方法中,super.h是父类Proxy中的一个属性:
Proxy.java:
/** * the invocation handler for this proxy instance. * @serial */ protected InvocationHandler h;