Java动态代理实现

  在java的动态代理机制中,有两个重要的类和接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

下面先贴上代码:

首先需要一个接口:

/* 
* @author zzf 
* @date 2018年12月5日 上午10:11:34 
*/
public interface People {
	
	/**
	 * 说话
	 * @param s
	 * @return
	 */
	public String say(String s);
	
	/**
	 * 吃饭
	 * @return
	 */
	public String eat();
	
	/**
	 * 睡觉
	 * @return
	 */
	public String sleep();
	
	/**
	 * 打豆豆
	 * @param name
	 * @param number
	 */
	public String bubbleSpinner(String name,Integer number);
}

这个接口需要一个实现类:


import java.lang.reflect.InvocationHandler;

/* 
* @author zzf 
* @date 2018年12月5日 上午10:21:14 
*/
public class PeopleImpl implements People{

	@Override
	public String say(String s) {
		// TODO Auto-generated method stub
		return s+"在说话";
	}

	@Override
	public String eat() {
		// TODO Auto-generated method stub
		return "吃饭";
	}

	@Override
	public String sleep() {
		// TODO Auto-generated method stub
		return "睡觉";
	}

	@Override
	public String bubbleSpinner(String name, Integer number) {
		// TODO Auto-generated method stub
		return name+":打豆豆"+",一天打"+number+"次";
	}

}

还需要 InvocationHandler的实现类:


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

/* 
* @author zzf 
* @date 2018年12月5日 上午10:26:10 
*/
public class MyInvocationHandler implements InvocationHandler {
	//被代理的对象
	T obj;
	//传入的name
	String name=null;
	
	public MyInvocationHandler(T obj,String name) {
		this.obj=obj;
		this.name=name;
	}
	
	public MyInvocationHandler(T obj) {
		this.obj=obj;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		if(name==null)
			name="无";
		System.out.println("代理对象开始前的骚操作:"+name);
		Object result = method.invoke(obj, args);
		System.out.println(result);
		System.out.println("代理对象开始结束后的骚操作:"+name);
		return result;
	}

}

创建JDK的动态代理主要有4个步骤:

1.创建InvocationHandler对象的实现(因为基于接口代理时它只有一个构造器可用)

Java动态代理实现_第1张图片

所以需要实现InvocationHandler。

		//创建被代理对象
		People people=new PeopleImpl();
		//创建InvocationHandler对象
		InvocationHandler stuHandler = new MyInvocationHandler(people);

2.使用Proxy类的getProxyClass静态方法生成一个动态代理类

Class proxyClass = Proxy.getProxyClass(People.class.getClassLoader(), new Class[] {People.class});

3.获得proxyClass 中一个带InvocationHandler参数的构造器constructor

Constructor constructor = proxyClass.getConstructor(InvocationHandler.class);

4.通过构造器constructor来创建一个动态实例proxy

People proxy = (People) constructor.newInstance(stuHandler);

最后调用proxy对象方法就行了。

/* 
* @author zzf 
* @date 2018年12月5日 上午10:24:31 
*/
public class Test {

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		// TODO Auto-generated method stub
		//创建被代理对象
		People people=new PeopleImpl();
		//创建InvocationHandler对象
		InvocationHandler stuHandler = new MyInvocationHandler(people);
		//使用Proxy类的getProxyClass静态方法生成一个动态代理类
		Class proxyClass = Proxy.getProxyClass(People.class.getClassLoader(), new Class[] {People.class});
		//获得proxyClass 中一个带InvocationHandler参数的构造器constructor
		Constructor constructor = proxyClass.getConstructor(InvocationHandler.class);
		//通过构造器constructor来创建一个动态实例proxy
		People proxy = (People) constructor.newInstance(stuHandler);
		//调用代理对象的方法
		System.out.println("返回结果:"+proxy.eat());
		proxy.bubbleSpinner("张三", 3);
		/******************************************************************/
		System.out.println();
		System.out.println();
		InvocationHandler stuHandler2 = new MyInvocationHandler(people,"唱歌这个骚操作");
		Class proxyClass2 = Proxy.getProxyClass(People.class.getClassLoader(), new Class[] {People.class});
		Constructor constructor2 = proxyClass2.getConstructor(InvocationHandler.class);
		People proxy2 = (People) constructor2.newInstance(stuHandler2);
		System.out.println("返回结果:"+proxy2.eat());
		proxy2.bubbleSpinner("张三", 3);
		/******************************************************************/
		System.out.println();
		System.out.println();
		People proxy3= (People) Proxy.newProxyInstance(People.class.getClassLoader(), new Class[]{People.class}, stuHandler);
		proxy3.eat();
		proxy3.bubbleSpinner("张三", 3);
	}

}

Java动态代理实现_第2张图片

另一种生成动态代理的快捷方式是通过Proxy的静态方法newProxyInstance来进行生成的:

InvocationHandler stuHandler = new MyInvocationHandler(people);
People proxy3= (People) Proxy.newProxyInstance(People.class.getClassLoader(), new Class[]{People.class}, stuHandler);

下面看一下JDK动态代理的newProxyInstance这个重要方法:

    public static Object newProxyInstance(ClassLoader loader,
                                          Class[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        //对象clone
        final Class[] intfs = interfaces.clone();
        //安全校验
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * 查找或生成指定的代理类。
         */
        Class cl = getProxyClass0(loader, intfs);

        //获取代理类的构造函数
        final Constructor cons = cl.getConstructor(constructorParams);
        /*    private static final Class[] constructorParams =
         *{ InvocationHandler.class };
         */
        final InvocationHandler ih = h;
        //根据代理类的构造函数来创建代理类对象
        return cons.newInstance(new Object[]{h});
    }

可以看到它内部也包含了以上几个步骤。

 

你可能感兴趣的:(Java,JDK动态代理)