在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对象的实现(因为基于接口代理时它只有一个构造器可用)
所以需要实现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);
}
}
另一种生成动态代理的快捷方式是通过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});
}
可以看到它内部也包含了以上几个步骤。