1. 静态代理
1.1 定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活 中常见的中介。
1.2 目的:
1.3 角色介绍:
- 抽象角色:指代理角色和真实角色对外提供的公共方法,一般为一个接口
- 真实角色:需要实现抽象角色接口,定义了真实角色所要实现的业务逻辑,以便供代理角色调用。也就是真正的业 务逻辑在此。
- 代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。将统一的流程控制都放到代理角色中处理!
1.4 使用样例代码:
以下是代理接口,该接口定义保存订单功能。
1 2 3
| public interface OrderService { int saveOrder(); }
|
以下是真实实现类。
1 2 3 4 5 6 7
| public class OutOrderServiceImpl implements OrderService { @Override public int saveOrder() { System.out.println("下单成功,订单号: 66666666"); return 66666666; } }
|
以下是代理类,代理持有真实实现类的对象,可以流程进行控制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class ProxyOrder implements OrderService {
private OrderService orderService = new OutOrderServiceImpl();
private void setOrderTag() { System.out.println("开始海外下订单"); }
@Override public int saveOrder() { setOrderTag(); return orderService.saveOrder(); }
|
2.动态代理
2.1 定义:通过反射机制,在运行时创建代理类
2.2 使用:
创建代理类,持有真实实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class ProxyHandler implements InvocationHandler {
private OrderService service;
public ProxyHandler(OrderService service) { this.service = service; }
@Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { System.out.println("before invoke -->"); method.invoke(service, objects); System.out.println("after invoke -->"); return null; } }
|
使用动态代理调用方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static void main(String[] args) { OrderService service = new OutOrderServiceImpl();
OrderService proxy = (OrderService)Proxy.newProxyInstance( service.getClass().getClassLoader(), service.getClass().getInterfaces(), new ProxyHandler(service));
proxy.saveOrder(); }
|
2.3 动态代理原理:
- 通过用户实现的InvocationHandler接口,获得真实处理事件的对象(相当于Proxy加了个传入真实实现对象监听);
- 通过newProxyInstance传入的ClassLoader和一组Interface来创建动态代理类;
- 通过反射获取动态代理类的构造方法,其构造函数的参数就是用户实现的InvocationHandler接口类;
- 通过构造函数创建动态代理类实例。
==============================生成动态代理类=============================================
下面我们详细来看一下Proxy是如何生成代理对象的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone();
Class<?> cl = getProxyClass0(loader, intfs);
try { final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { cons.setAccessible(true); } return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { } }
|
下面我们来看一下是如何生成这个Class对象的
1 2 3 4 5 6 7 8 9 10 11
| private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); }
return proxyClassCache.get(loader, interfaces); }
|
下面来看一下ProxyClassFactory是如何创建代理对象的。(在Proxy中有一个ProxyClassFactory静态内部类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { Class<?> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " is not visible from class loader"); } if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } }
String proxyPkg = null; int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
for (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { accessFlags = Modifier.FINAL; String name = intf.getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces from different packages"); } } }
if (proxyPkg == null) { proxyPkg = ""; }
{ List<Method> methods = getMethods(interfaces); Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE); validateReturnTypes(methods); List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
Method[] methodsArray = methods.toArray(new Method[methods.size()]); Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num;
return generateProxy(proxyName, interfaces, loader, methodsArray, exceptionsArray); } }
|
最后通过调用native的generateProxy()方法生成class类
1 2 3 4
| private static native Class<?> generateProxy(String name, Class<?>[] interfaces, ClassLoader loader, Method[] methods, Class<?>[][] exceptions);
|
在Android中生成class类是在navite中生成的。在java中最终是调用ProxyGenerator.generateProxyClass()生成byte数组,最后调用defineClass0()将byte数组转化成class类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) { ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); final byte[] var4 = var3.generateClassFile(); if(saveGeneratedFiles) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { try { int var1 = var0.lastIndexOf(46); Path var2; if(var1 > 0) { Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar), new String[0]); Files.createDirectories(var3, new FileAttribute[0]); var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class"); } else { var2 = Paths.get(var0 + ".class", new String[0]); }
Files.write(var2, var4, new OpenOption[0]); return null; } catch (IOException var4x) { throw new InternalError("I/O exception saving generated file: " + var4x); } } }); }
return var4; }
|
生成代理类字节码文件的generateClassFile方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| private byte[] generateClassFile() { 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(); 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() > '\uffff') { throw new IllegalArgumentException("method limit exceeded"); } else if(this.fields.size() > '\uffff') { 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); } } }
|
调用generateClassFile()之后,就会生成class类的byte数组。
为了验证这个结论,写一个demo:
1 2 3 4 5 6 7 8
| private static void proxy() throws Exception { String name = OrderService.class.getName() + "$Proxy0"; byte[] bytes = ProxyGenerator.generateProxyClass(name, new Class[]{OrderService.class}); FileOutputStream fos = new FileOutputStream("C:\\Users\\gz04766\\Desktop\\" + name + ".class"); fos.write(bytes); fos.close(); }
|
至此,我们分析清楚了Proxy是如何生成代理class类的。
================================如何完成动态调用========================================
当通过反射调用构造方法的时候,将用户实现的InvocationHandler传给Proxy。在生成的类中,通过反射拿到接口定义的Method方法。最后通过父类的中的InvocationHandler的invoke方法,最终调入到自定义的InvocationHandler中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public final class OrderService$Proxy0 extends Proxy implements OrderService { private static Method m1; private static Method m3; private static Method m2; private static Method m0;
public OrderService$Proxy0(InvocationHandler var1) throws { super(var1); } public final int saveOrder() throws { try { return (Integer)super.h.invoke(this, m3, (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")); m3 = Class.forName("com.gac.oj.OrderService").getMethod("saveOrder"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } ..... }
|