静态代理
静态代理使用硬编码的方式实现代理。
public interface Singer {
public void sing();
}
提供实现类
public class Linjunjie implements Singer {
@Override
public void sing() {
System.out.println("全都怪我,不该沉默时沉默。。。。");
}
}
代理类
public class ProxySinger implements Singer{
private Singer proxy;
public ProxySinger(Singer singer){
proxy = singer;
}
@Override
public void sing() {
System.out.println("前置增强处理。。");
proxy.sing();
System.out.println("后置增强处理。。");
}
}
测试
Singer singer = new ProxySinger(new Linjunjie());
singer.sing();
前置增强处理。。
全都怪我,不该沉默时沉默。。。。
后置增强处理。。
JDK 动态代理
为接口中的方法提供对应的代理增强。
- 只有接口中的方法,才会有对应的代理方法
- 除此之外,还有一些方法也提供了代理。 (toString、hashCode、equals)。从这个层面上来讲,Interface 其实继承了Object
Object中的非本地 public 方法只有toString、hashCode、equals
JDK 代理的流程:
- 生成代理类的源码文件
- 编译、加载源码文件,并生成代理对象
- 调用代理对象的方法,触发 回调函数
invoke
定义接口类
public interface Singer {
public void sing();
}
提供实现类
public class Linjunjie implements Singer {
@Override
public void sing() {
System.out.println("全都怪我,不该沉默时沉默。。。。");
}
}
定义回调函数
public class MyHandler implements InvocationHandler {
private Object proxy;
public MyHandler(Object object) {
proxy = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前奏准备");
Object obj = method.invoke(this.proxy, args);
System.out.println("高潮不断");
return obj;
}
public Object getInstance() {
return Proxy.newProxyInstance(proxy.getClass().getClassLoader(),proxy.getClass().getInterfaces(), this);
}
}
测试类
// 保存生成的代理类的字节码文件
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// 回调方法
MyHandler myHandler = new MyHandler(new Linjunjie());
Singer singer = (Singer) myHandler.getInstance();
singer.sing();
代理类源码文件
生成文件位置的
生成的源码文件
package com.sun.proxy;
import design.proxy.Singer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Singer {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
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 void sing() throws {
try {
super.h.invoke(this, m3, (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);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("design.proxy.Singer").getMethod("sing");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
Method m3 = Class.forName("design.proxy.Singer").getMethod("sing");
public final void sing() throws {
try {
// 代理类继承 Proxy,此处h为InvocationHandler
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
【Proxy】
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
【Proxy.ProxyClassFactory】,通过 ProxyClassFactory 生成字节流源码文件。
// 包名 + $Proxy + 自增的数字
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// 生成二进制文件
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);