JDK动态代理
1.动态代理
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。
2.类图
其中Proxy$0是生成的代理类。
3.实现
1.接口Subject和Subject2
interface Subject {
String Do();
void unDo();
}
public interface Subject2 {
int add(int a,int b);
}
2.RealSubject
public class RealSubject implements Subject,Subject2{
public String Do() {
return "Hello Word";
}
public void unDo() {
System.out.println("undo");
}
public int add(int a, int b) {
return a+b;
}
}
3.InvocationHandlerImpl
public class InvocationHandlerImpl implements InvocationHandler {
Object object;
public InvocationHandlerImpl(Object object) {
this.object = object;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//在代理真实对象前我们可以添加一些自己的操作
System.out.println("在调用之前,我要干点啥呢?");
System.out.println("Method:" + method);
//当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
Object returnValue = method.invoke(object, args);
//在代理真实对象后我们也可以添加一些自己的操作
System.out.println("在调用之后,我要干点啥呢?");
return returnValue;
}
}
4.Main
public class Main {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(realSubject);
ClassLoader loader = realSubject.getClass().getClassLoader();
Class[] interfaces = realSubject.getClass().getInterfaces();
Subject2 proxy = (Subject2) Proxy.newProxyInstance(loader,interfaces,invocationHandler);
System.out.println(proxy.add(2,4));
}
}
结果:
4.原理
//通过该方法生成代理类的字节码。
//proxyName为代理类的类名。
//interfaces为被代理类的实现的接口数组。
//accessFlags为代理类的类访问控制符(public , final等)
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
//ReflectUtil.PROXY_PACKAGE==com.sun.proxy
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
最终调用下面的方法生成代理类字节码:
private byte[] generateClassFile() {
//添加下述的3个Object.class方法
this.addProxyMethod(hashCodeMethod, Object.class);
this.addProxyMethod(equalsMethod, Object.class);
this.addProxyMethod(toStringMethod, Object.class);
Class[] var1 = this.interfaces;
int var2 = var1.length;
int var3;
Class var4;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
Method[] var5 = var4.getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method var8 = var5[var7];
//添加代理接口中的方法
this.addProxyMethod(var8, var4);
}
}
Iterator var11 = this.proxyMethods.values().iterator();
List var12;
while(var11.hasNext()) {
var12 = (List)var11.next();
checkReturnTypes(var12);
}
Iterator var15;
try {
this.methods.add(this.generateConstructor());
var11 = this.proxyMethods.values().iterator();
while(var11.hasNext()) {
var12 = (List)var11.next();
var15 = var12.iterator();
while(var15.hasNext()) {
ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();
//为代理类添加属性(m0,m1,m2.....)
this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));
//添加方法
this.methods.add(var16.generateMethod());
}
}
this.methods.add(this.generateStaticInitializer());
} catch (IOException var10) {
throw new InternalError("unexpected I/O Exception", var10);
}
if (this.methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
} else if (this.fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
} else {
//添加常量池
this.cp.getClass(dotToSlash(this.className));
this.cp.getClass("java/lang/reflect/Proxy");
var1 = this.interfaces;
var2 = var1.length;
for(var3 = 0; var3 < var2; ++var3) {
var4 = var1[var3];
this.cp.getClass(dotToSlash(var4.getName()));
}
this.cp.setReadOnly();
ByteArrayOutputStream var13 = new ByteArrayOutputStream();
DataOutputStream var14 = new DataOutputStream(var13);
//写入字节数组
try {
var14.writeInt(-889275714);
var14.writeShort(0);
var14.writeShort(49);
this.cp.write(var14);
var14.writeShort(this.accessFlags);
var14.writeShort(this.cp.getClass(dotToSlash(this.className)));
var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));
var14.writeShort(this.interfaces.length);
Class[] var17 = this.interfaces;
int var18 = var17.length;
for(int var19 = 0; var19 < var18; ++var19) {
Class var22 = var17[var19];
var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));
}
var14.writeShort(this.fields.size());
var15 = this.fields.iterator();
while(var15.hasNext()) {
ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();
var20.write(var14);
}
var14.writeShort(this.methods.size());
var15 = this.methods.iterator();
while(var15.hasNext()) {
ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();
var21.write(var14);
}
var14.writeShort(0);
return var13.toByteArray();
} catch (IOException var9) {
throw new InternalError("unexpected I/O Exception", var9);
}
}
}
5.反编译生成的代理类字节码
1.代码
//将代理类的字节码数组,写入一个class文件中。
public class GeneratorProxyClass {
public static void main(String[] args) throws Exception{
RealSubject realSubject = new RealSubject();
Class[] interfaces = realSubject.getClass().getInterfaces();
String proxyName = "MyProxyClass";//为我们生成的代理类叫一个名字
//调用上面的ProxyGenerator.generateProxyClass()方法生成代理类字节码
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, 17);
//将字节码写入该文件
File file = new File("MyProxyClass.class");
FileOutputStream fos = new FileOutputStream(file);
fos.write(proxyClassFile);
fos.flush();
fos.close();
}
}
2.查看反编译后类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import Designpattern.JDK_Proxy.Subject;
import Designpattern.JDK_Proxy.Subject2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
//该类继承Proxy,实现了接口。
public final class MyProxyClass extends Proxy implements Subject, Subject2 {
//类的静态属性,会在该类加载是被赋值。
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m5;
private static Method m3;
private static Method m0;
//构造函数,组和了一个InvocationHandler
public MyProxyClass(InvocationHandler var1) throws {
super(var1);
}
//super.h为父类Proxy组和进去的InvocationHandler对象。
/*
public class Proxy implements java.io.Serializable {
protected InvocationHandler h;
....
}
*/
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 void unDo() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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 add(int var1, int var2) throws {
try {
return (Integer)super.h.invoke(this, m5, new Object[]{var1, var2});
} catch (RuntimeException | Error var4) {
throw var4;
} catch (Throwable var5) {
throw new UndeclaredThrowableException(var5);
}
}
public final String Do() throws {
try {
return (String)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"));
m4 = Class.forName("Designpattern.JDK_Proxy.Subject").getMethod("unDo");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m5 = Class.forName("Designpattern.JDK_Proxy.Subject2").getMethod("add", Integer.TYPE, Integer.TYPE);
m3 = Class.forName("Designpattern.JDK_Proxy.Subject").getMethod("Do");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}