jdk动态代理

一、代理简要介绍:

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();
}

(2)定义接口实现类

package com.my.proxy;

public class HelloWorldImpl implements IHelloWorld {

    @Override
    public void sayHi() {
        // TODO Auto-generated method stub
        System.out.println("hello world");
    }

}

(3)定义代理类:

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;
    }

}

(4)代理类测试

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();
    }
    
}


(5)动态生成的字节码文件

// 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;

所以最后都是调用InvocationHandler的invoke方法来实现相应逻辑,在代理类HelloWorldProxy中的invoke( Object proxy, Method method, Object[] args)方法,参数proxy虽然没在 HelloWorldProxy中任何地方使用,但是其代表的就是动态生成的代理类,可以看做是$Proxy0的实例对象




你可能感兴趣的:(jdk动态代理)