定义
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
实现方式
在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。
java.lang.reflect.InvocationHandler#invoke
//proxy:指我们所代理的那个真实对象//method:真实对象调用的方法//args:传入方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
可以看出,现在还不知道代理类对象是什么,这用到了另一个类:java.lang.reflect.Proxy
Proxy类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法
//返回 动态的代理对象
//loader: 加载代理对象的ClassLoader//interfaces:一个Interface对象的数组,代理类实现的这些接口列表//h:关联到的InvocationHandler对象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Java代码案例:
package com.tlk.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Created by tanlk on 2017/8/16 17:32.
*/
public class JDKDynamicProxyTest {
interface Subject {
public void test1();
public void test2();
}
/**
* 实现类1
*/
static class MySubject1 implements Subject {
public void test1() {
System.out.println("MySubject1 test1 方法开始执行");
}
public void test2() {
System.out.println("MySubject1 test2 方法开始执行");
}
}
/**
* 实现类2
*/
static class MySubject2 implements Subject {
public void test1() {
System.out.println("MySubject2 test1 方法开始执行");
}
public void test2() {
System.out.println("MySubject2 test2 方法开始执行");
}
}
/**
* 定义一个动态代理类,动态代理类必须要实现InvocationHandler接口
*/
static class DynamicProxy implements InvocationHandler {
private Subject target;
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before ");
method.invoke(target, args);
System.out.println("end");
return null;
}
//通过Proxy的newProxyInstance方法来创建我们的代理对象
public Object getProxy(Subject target) {
this.target = target;
//动态生成代理类
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
public static void main(String[] args) {
DynamicProxy dynamicProxy = new DynamicProxy();
Subject subject = (Subject) dynamicProxy.getProxy(new MySubject1());
System.out.println("生成的代理类:" + subject.getClass());
subject.test1();
subject = (Subject) dynamicProxy.getProxy(new MySubject2());
System.out.println("生成的代理类:" + subject.getClass());
subject.test2();
}
}
动态代理优点:
1.上面只有一个proxy类,但可以代理多个实现,而静态代理需要n个proxy类
2.通过invoke方法,在所有被代理的类的某些函数调用时触发,一口气完成所有对应代理的AOP(静态代理需要在每个代理上进行AOP)