一、动态代理用来干什么
1、动态代理可以实现对接口的装饰,可以在一个方法执行之前和之后选择不同的操作(对于特别多方法的接口而言,会很方便)
2、各种框架里都使用动态代理,那么我们也没有理由不去学习和应用它
二、原理
java中的动态代理主要是两个类:Proxy和InvocationHandler
Proxy: 生成代理对象
InvocationHandler: 拦截对象,进行方法的校验或者增强
创建Proxy有两种方法
//这是Proxy的静态方法,用来生成代理类,代理类实现了interfaces定义的接口,类名以$Proxy开头,所以源码特别注明"请原则上不用以这个字符串命名类,尽管没有强制性的要求"
getProxyClass(ClassLoader loader,Class<?>... interfaces)
//拿到Proxy类之后,我们可以获取它的构造构造方法并进行实例化
getConstructor(InvocationHandler.class);
//获取动态代理对象,之后我们就可以随意调用方法了
newInstance(Object ... initargs)
//直接一步到位,创建代理对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
在这里我们可以看到都有使用InvocationHandler,这个类就是执行代理对象代理的方法
三、使用
1、勤快式
所为勤快式,就是我们可以先创建出Constructor对象,然后new Proxy时,再进行newInstance
public class MyInvocationHandler implements InvocationHandler {
private final MergeFun mergeFun;
public MyInvocationHandler(MergeFun mergeFun){
this.mergeFun = mergeFun;
}
private final static Constructor CONSTRUCTOR;
static {
try {
CONSTRUCTOR = Proxy.getProxyClass(MyInvocationHandler.class.getClassLoader(), new Class[]{Function1.class, Function2.class})
.getConstructor(InvocationHandler.class);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException(e);
}
}
/**
* 定义成static
* @param mergeFun
* @return
*/
public static Function1 newProxy(final MergeFun mergeFun){
try {
return (Function1) CONSTRUCTOR.newInstance(new MyInvocationHandler(mergeFun));
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new IllegalArgumentException(e);
} catch (InvocationTargetException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke start");
Object object = method.invoke(mergeFun, args);
System.out.println("invoke result:" + object);
return object;
}
}
2、懒惰式
使用时再进行new instance
public class MyLazyProxy implements InvocationHandler {
private MergeFun mergeFun;
public MyLazyProxy(MergeFun my){
this.mergeFun = my;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke start");
Object object = method.invoke(mergeFun, args);
System.out.println("invoke result:" + object);
return object;
}
public static Function1 newProxy(final MergeFun mergeFun){
return (Function1) Proxy.newProxyInstance(MyLazyProxy.class.getClassLoader(),
new Class[]{Function1.class}, new MyLazyProxy(mergeFun));
}
}
注:MergeFun 就是要被代理的真实对象