静态代理都是针对要代理的对象的方法写死成Java代码,然后调用静态代理对象的对应方法即可。
动态代理就是一个代理对象,可以对传入的任何对象动态的生产代理对象,然后就可以通过代理对象调用目标方法。
下面是JDK的动态代理示例:
// JDK动态代理的对象类必须实现接口
// 接口
public interface Subject {
void request();
void response();
}
// 目标对象类,实现接口
public class SubjectImpl implements Subject {
public void request() {
System.out.println("执行 request 方法了。。。");
}
public void response() {
System.out.println("执行 response 方法了。。。");
}
}
JDK动态代理对象必须要实现 InvocationHandler 接口(JDK反射包里的接口)。
public class SubjectJDKProxy implements InvocationHandler {
private Subject subject;
public void setSubject(Subject subject) {
this.subject = subject; // 设置代理的目标对象
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 执行目标方法前的非业务功能
System.out.println("before 前置通知");
Object result;
try {
// 执行目标方法
result = method.invoke(subject, args);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
// 执行目标方法后的非业务功能
System.out.println("after 后置通知");
}
return result;
}
}
获取代理对象:
public class JDKProxyMain {
public static void main(String{} args) {
SubjectJDKProxy handler = new SubjectJDKProxy(new SubjectImpl());
// 获取代理对象
Subject subject = (Subject)Proxy.newProxyInstance(JDKProxyMain.class.getClassLoader, new Class[]{Subject.class}, handler);
subject.request();
subject.response();
}
}
输出结果:
before 前置通知
执行 request 方法了。。。
after 后置通知
before 前置通知
执行 response 方法了。。。
after 后置通知
可以参考 代理模式详解及源码分析 知道,代理对象的源码:
public final class $Proxy0 extends Proxy implements Subject { // 继承父类Proxy,实现自定义接口Subject
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
m4 = Class.forName("mike.test.Starter").getMethod("request");
m3 = Class.forName("mike.test.Starter").getMethod("response");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
public $Proxy0(InvocationHandler var1) throws { // 构造方法接收代理人,并调用Proxy父类构造方法
super(var1);
}
public final void request() throws { // 实际上其实是调用了代理人SubjectJDKProxy的invoke方法(h 其实就是我们所创建的 subjectJDKProxy 对象,m4 就是目标类实现接口中的方法)
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void response() throws { // 实际上其实是调用了代理人SubjectJDKProxy的invoke方法
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
// 以下就是Object类通用方法的覆盖,不多赘述
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
所以,这段代码的作用就是生成最终的代理对象,方式就是获取到 Subject.class 接口中的所有方法,生成一个新的字节码类,在字节码类中注入 属性 handler,通过 handler 的 invok 方法调用目标对象的方法。
Proxy.newProxyInstance(JDKProxyMain.class.getClassLoader, new Class[]{Subject.class}, handler)