JDK动态代理是利用接口,在JVM运行阶段动态生成Class,没错,它是在运行阶段生成的,是和字节码相关的一种操作。
JDK动态代理可以提供对代理对象的访问,可以在对象接口方法的前后处理一些逻辑,使被代理的对象的关注于自身的功能逻辑。JDK动态代理会实现它所表示的实际对象的接口,因此实现接口是最基本的需要。代理对象隐藏了实际对象,因此用户不知道是同代理做交互还是同对象本身做交互。
JDK动态代理首先要有一个动态类,该类得实现接口InvocationHandler。由于JDK代理是基于接口的,所以代理的对象需要实现接口,然后通过Proxy.newProxyInstance方法为目标对象生成代理对象。
代码示例如下:
/**
* 对象实现的接口
*/
interface Hello {
public void say();
}
/**
* 接口的实现
*/
class HelloImpl implements Hello {
public void say() {
System.out.println("say");
}
}
/**
* 代理类的实现 实现了InvocationHandler
*/
class DynamicProxy implements InvocationHandler {
private Object targetObject;
public DynamicProxy(Object targetObject) {
this.targetObject = targetObject;
}
public void before() {
System.out.println("before-----");
}
public void after() {
System.out.println("after------");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
before();
method.invoke(targetObject, args);
after();
return null;
}
}
入口main如下
public static void main(String[] args) throws Exception {
Hello helloTarget = new HelloImpl();
DynamicProxy dynamicProxy = new DynamicProxy(helloTarget);
/*
* Proxy.newProxyInstance(ClassLoader classLoader, Class<?>[] interface, InvocationHandler invocationHandler)
* 有三个参数
* 第一个为classLoader,这里使用HelloImpl的类加载器
* 第二个为受代理的对象实现的接口,在这里也就是Hello
* 第三个为InvocationHandler接口的实现对象,在这里也就是dynamicProxy
* 该方法返回一个jvm动态生成的一个代理对象,该对象实现了Hello接口,该对象的class是动态生成的
*/
Hello hello = (Hello)Proxy.newProxyInstance(helloTarget.getClass().getClassLoader(),
helloTarget.getClass().getInterfaces(), dynamicProxy);
hello.say();
System.out.println(hello.getClass().getName());
}
输出如下:
before-----
say
after------
com.my.servlet.$Proxy0
从输出结果和代码可以看出,Proxy.newProxyInstance生成的代理对象实现了Hello接口,同时,该对象的class是一个com.my.servlet.