JDK动态代理
核心思想:通过实现被代理类的所有接口,生成一个字节码文件后构造一个代理对象,通过持有反射构造被代理类的一个实例,再通过invoke反射调用被代理类实例的方法,来实现代理。
缺点:JDK动态代理的对象必须实现一个或多个接口

流程图
知识点
- JDK实现动态代理需要实现类通过接口定义业务方法
- JDK生成的代理类以"$Proxy"为开头进行命名
- JDK代理生成的代理类的Method在static静态代码块中进行初始化;
- public接口生成的代理类package为"com.sun.proxy";
- JDK动态代理需要实现InvocationHandler接口;
代码:
package com.quancheng;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy {
public static void main(String[] args) {
Student stu = new Student();
CusInvocationHandler handler = new CusInvocationHandler(stu);
Play instance = (Play) Proxy.newProxyInstance(stu.getClass().getClassLoader(), stu.getClass().getInterfaces(), handler);
instance.play();
}
}
class CusInvocationHandler implements InvocationHandler {
private Object target;
public CusInvocationHandler(Object object) {
this.target = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.err.println("代理方法处理");
return method.invoke(target, args);
}
}
interface Play {
void play();
}
class Student implements Play {
@Override
public void play() {
System.err.println("student ====>");
}
}
生成的代理类示例:
import dynamic.proxy.UserService;
import java.lang.reflect.*;
public final class $Proxy11 extends Proxy
implements UserService
{
// 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例
public $Proxy11(InvocationHandler invocationhandler)
{
super(invocationhandler);
}
public final boolean equals(Object obj)
{
// 省略
}
/**
* 被代理的方法
*/
public final void add()
{
try
{
// 实际上就是调用MyInvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法,第二个问题就解决了
super.h.invoke(this, m3, null);
return;
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode()
{
// 省略
}
public final String toString()
{
// 省略
}
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;
// 在静态代码块中获取了4个方法:Object中的equals方法、UserService中的add方法、Object中的hashCode方法、Object中toString方法
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
Class.forName("java.lang.Object")
});
m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
}
catch(NoSuchMethodException nosuchmethodexception)
{
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
}
