代理模式
代理模式给某一个对象提供一个代理对象,并由代理对象管制对原对象的援用。
动态代理
代理类HelloProxy
public class HelloProxy implements HelloInterface{ private HelloInterface helloInterface = new Hello(); @Override public void sayHello() { System.out.println("Before invoke sayHello" ); helloInterface.sayHello(); System.out.println("After invoke sayHello"); }}
接口HelloInterface
public interface HelloInterface { void sayHello();}
继承接口的办法Hello
public class Hello implements HelloInterface{ @Override public void sayHello() { System.out.println("Hello Zero!"); }}
主函数
public class Main { public static void main(String[] args) { HelloProxy helloProxy = new HelloProxy(); helloProxy.sayHello(); }}
运行后果
Before invoke sayHelloHello Zero!After invoke sayHello
应用动态代理实现了对一个类的代理操作。然而动态代理也有毛病:因为代理只能为一个类服务,如果须要代理的类很多,那么就须要编写大量的代理类,比拟繁琐。
动静代理
利用反射机制在运行时创立代理类。
接口和继承接口的办法不变。
代理类ProxyHandler
创立代理类,继承自InvocationHandler,InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用办法时,办法调用被编码分派到调用处理程序的invoke办法。
每一个动静代理类的调用处理程序都必须实现InvocationHandler接口,并且每个代理类的实例都关联到了实现该接口的动静代理类调用处理程序中,当咱们通过动静代理对象调用一个办法时候,这个办法的调用就会被转发到实现InvocationHandler接口类的invoke办法来调用。
public class ProxyHandler implements InvocationHandler { private Object object; public ProxyHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before invoke " + method.getName()); method.invoke(object, args); System.out.println("After invoke " + method.getName()); return null; }}
主函数
public class Main { public static void main(String[] args) { //将JDK动静代理生成的class文件保留到本地 System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); HelloInterface hello = new Hello(); InvocationHandler handler = new ProxyHandler(hello); HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler); proxyHello.sayHello(); }}
运行后果
Before invoke sayHelloHello Zero!After invoke sayHello
咱们能够看到办法失常执行了,主函数中通过Proxy类的静态方法newProxyInstance返回一个接口的代理实例,针对不同的代理类,传入相应的代理程序控制器InvocationHandler,就能够返回相应的代理实例。
比方:新建几个办法
public class Cat implements CatInterface { @Override public void say() { System.out.println("I'm Cat"); }}
public interface CatInterface { void say();}
public class Mouse implements MouseInterface { @Override public void say() { System.out.println("I'm mouse"); }}
public interface MouseInterface { void say();}
再执行主函数
public class Main { public static void main(String[] args) { //将JDK动静代理生成的class文件保留到本地 System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true"); HelloInterface hello = new Hello(); InvocationHandler handler = new ProxyHandler(hello); HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler); proxyHello.sayHello(); MouseInterface mouse = new Mouse(); CatInterface cat = new Cat(); InvocationHandler handlerMouse = new ProxyHandler(mouse); InvocationHandler handlerCat = new ProxyHandler(cat); MouseInterface proxyMouse = (MouseInterface) Proxy.newProxyInstance(mouse.getClass().getClassLoader(), mouse.getClass().getInterfaces(), handlerMouse); CatInterface proxyCat = (CatInterface) Proxy.newProxyInstance(cat.getClass().getClassLoader(), cat.getClass().getInterfaces(), handlerCat); proxyMouse.say(); proxyCat.say(); }}
后果如下,所有办法失常执行
Before invoke sayHelloHello Zero!After invoke sayHelloBefore invoke sayI'm mouseAfter invoke sayBefore invoke sayI'm CatAfter invoke say
动静代理的实现
- 通过实现 InvocationHandler 接口创立本人的调用处理器;
- 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创立动静代理类;
- 通过反射机制取得动静代理类的构造函数,其惟一参数类型是调用处理器接口类型;
- 通过构造函数创立动静代理类实例,结构时调用处理器对象作为参数被传入;
Proxy.newProxyInstance
package java.lang.reflect; public class Proxy implements java.io.Serializable { /** * Returns an instance of a proxy class for the specified interfaces 返回指定接口的代理类的实例,该实例将办法调用分派到指定的调用处理程序。 * that dispatches method invocations to the specified invocation * handler. * * <p>{@code Proxy.newProxyInstance} throws * {@code IllegalArgumentException} for the same reasons that * {@code Proxy.getProxyClass} does. * * @param loader the class loader to define the proxy class @param loader类加载器,用于定义代理类 * @param interfaces the list of interfaces for the proxy class @param interfaces代理类要实现的接口列表 * to implement * @param h the invocation handler to dispatch method invocations to @param h调用处理程序,以分派办法调用以应用指定类加载器定义并实现指定接口的代理类的指定调用处理程序来返回代理实例。 * @return a proxy instance with the specified invocation handler of a * proxy class that is defined by the specified class loader * and that implements the specified interfaces * @throws IllegalArgumentException if any of the restrictions on the @throws IllegalArgumentException,如果对可能传递给{@code getProxyClass}的参数被违反 * parameters that may be passed to {@code getProxyClass} * are violated * @throws SecurityException if a security manager, <em>s</em>, is present 如果存在平安管理器<em> s </ em>并且满足以下任何条件,则@throws SecurityException: * and any of the following conditions is met: * <ul> * <li> the given {@code loader} is {@code null} and 给定的{@code loader}为{@code null},而调用者的类加载器不是{@code null},并应用{@code RuntimePermission(“ getClassLoader”)调用 * the caller's class loader is not {@code null} and the {@link SecurityManager#checkPermission s.checkPermission} “)}权限回绝拜访; * invocation of {@link SecurityManager#checkPermission * s.checkPermission} with * {@code RuntimePermission("getClassLoader")} permission * denies access;</li> * <li> for each proxy interface, {@code intf}, 对于每个代理接口{@code intf},调用者的类加载器与{@code intf}和调用{@link SecurityManager#checkPackageAccess * the caller's class loader is not the same as or an s.checkPackageAccess()的类加载器都不雷同或不雷同}回绝拜访{@code intf}; * ancestor of the class loader for {@code intf} and * invocation of {@link SecurityManager#checkPackageAccess * s.checkPackageAccess()} denies access to {@code intf};</li> * <li> any of the given proxy interfaces is non-public and the 任何给定的代理接口都是非公共的,并且调用方类与非公共接口不在同一个{@linkplain软件包运行时软件包}中,并且应用以下命令调用{@link * caller class is not in the same {@linkplain Package runtime package} SecurityManager#checkPermission s.checkPermission} {@code ReflectPermission(“ newProxyInPackage。{package name}”)}权 * as the non-public interface and the invocation of 限回绝拜访。 * {@link SecurityManager#checkPermission s.checkPermission} with * {@code ReflectPermission("newProxyInPackage.{package name}")} * permission denies access.</li> * </ul> * @throws NullPointerException if the {@code interfaces} array * argument or any of its elements are {@code null}, or * if the invocation handler, {@code h}, is * {@code null} */ @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { //判断InvocationHandler是否为空,若为空,抛出空指针异样 Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class.查找或生成指定的代理类对象 */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler.用指定的调用处理程序调用其构造函数 */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; //如果Class作用域为公有,通过反射 setAccessible 反对拜访 if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //获取Proxy Class构造函数,创立Proxy代理实例。 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }
Proxy.getProxyClass0
利用getProxyClass0(loader, intfs)生成代理类Proxy的Class对象
package java.lang.reflect; public class Proxy implements java.io.Serializable { /** * a cache of proxy classes 在此初始化WeakCache */ private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); /** * Generate a proxy class. Must call the checkProxyAccess method 生成代理类。 在调用此办法之前,必须调用checkProxyAccess办法执行权限查看。 * to perform permission checks before calling this. */ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { //如果接口数量大于65535,抛出非法参数谬误 throw new IllegalArgumentException("interface limit exceeded"); } // If the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the ProxyClassFactory //如果存在由实现了给定接口的给定加载器定义的代理类,则将仅返回缓存的正本;否则,它将通过ProxyClassFactory创立代理类。 return proxyClassCache.get(loader, interfaces); }
WeakCache.get(K key, P parameter)
其中缓存应用WeakCache实现,应用ProxyClassFactory创立代理,ProxyClassFactory是Proxy类的动态外部类,实现了BiFunction接口中的apply办法,当WeakCache中没有缓存相应接口的代理类,则会调用ProxyClassFactory类的apply办法来创立代理类。
package java.lang.reflect; final class WeakCache<K, P, V> { /** * Look-up the value through the cache. This always evaluates the 通过缓存查找值。如果缓存中没有给定的条目或者实体曾经被革除,这总是评估{@code subKeyFactory}函数,并有选择地评估{@code valueFactory}函数 * {@code subKeyFactory} function and optionally evaluates * {@code valueFactory} function if there is no entry in the cache for given * pair of (key, subKey) or the entry has already been cleared. * * @param key possibly null key @param键可能为空键 * @param parameter parameter used together with key to create sub-key and * value (should not be null) * @return the cached value (never null) * @throws NullPointerException if {@code parameter} passed in or * {@code sub-key} calculated by * {@code subKeyFactory} or {@code value} * calculated by {@code valueFactory} is null. */ public V get(K key, P parameter) { Objects.requireNonNull(parameter); expungeStaleEntries(); Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level valuesMap for the particular cacheKey // 懒加载 为特定的cacheKey设置第二级valuesMap ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { //如果valuesMap为null,就新建一个,如果不为null,就取oldValue ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // create subKey and retrieve the possible Supplier<V> stored by that 创立subKey并从valuesMap中检索该subKey存储的可能的Supplier<V> // subKey from valuesMap Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); //获取supplier Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; //自旋,期待supplier不为空 while (true) { if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance // 如果缓存中没有,就调用ProxyClassFactory办法创立 此时supplier是WeakCache$Factory,调用WeakCache中Factory的get办法 V value = supplier.get(); if (value != null) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared CacheValue // or a Factory that wasn't successful in installing the CacheValue) // lazily construct a Factory 工厂懒加载,在此初始化并结构factory为WeakCache$Factory if (factory == null) { factory = new Factory(key, parameter, subKey, valuesMap); } if (supplier == null) { //从valuesMap中加载 supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory // 从valuesMap中还是得不到,就应用factory赋值supplier,赋值后supplier不为null,while自旋将失效 supplier = factory; } // else retry with winning supplier } else { if (valuesMap.replace(subKey, supplier, factory)) { // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // retry with current supplier supplier = valuesMap.get(subKey); } } } }
WeakCache.Factory
package java.lang.reflect; final class WeakCache<K, P, V> { /** * A factory {@link Supplier} that implements the lazy synchronized 工厂{@link Supplier}实现了值的惰性同步结构并将其装置到缓存中。 * construction of the value and installment of it into the cache. */ private final class Factory implements Supplier<V> { private final K key; private final P parameter; private final Object subKey; private final ConcurrentMap<Object, Supplier<V>> valuesMap; Factory(K key, P parameter, Object subKey, ConcurrentMap<Object, Supplier<V>> valuesMap) { this.key = key; this.parameter = parameter; this.subKey = subKey; this.valuesMap = valuesMap; } @Override public synchronized V get() { // serialize access // re-check Supplier<V> supplier = valuesMap.get(subKey); if (supplier != this) { // something changed while we were waiting: // might be that we were replaced by a CacheValue // or were removed because of failure -> // return null to signal WeakCache.get() to retry // the loop return null; } // else still us (supplier == this) // create new value V value = null; try { //调用Proxy类中动态外部类ProxyClassFactory的apply创立代理类 valueFactory此时是Proxy.ProxyClassFactory value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { if (value == null) { // remove us on failure valuesMap.remove(subKey, this); } } // the only path to reach here is with non-null value assert value != null; // wrap value with CacheValue (WeakReference) CacheValue<V> cacheValue = new CacheValue<>(value); // try replacing us with CacheValue (this should always succeed) if (valuesMap.replace(subKey, this, cacheValue)) { // put also in reverseMap reverseMap.put(cacheValue, Boolean.TRUE); } else { throw new AssertionError("Should not reach here"); } // successfully replaced us with new CacheValue -> return the value // wrapped by it return value; } }
Proxy.ProxyClassFactory
package java.lang.reflect; public class Proxy implements java.io.Serializable { /** * A factory function that generates, defines and returns the proxy class given * the ClassLoader and array of interfaces. */ private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // prefix for all proxy class names // 代理类前缀 private static final String proxyClassNamePrefix = "$Proxy"; // next number to use for generation of unique proxy class names // 生成代理类名称的计数器,原子性,包证多线程状况可用 private static final AtomicLong nextUniqueNumber = new AtomicLong(); @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); for (Class<?> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. * 校验类加载器是否能通过接口名称加载该类 */ 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"); } /* * Verify that the Class object actually represents an * interface. * 校验该类是否是接口类型 JAVA是单继承的,代理类曾经继承了Proxy类了,不能再继承其余的类 */ if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * Verify that this interface is not a duplicate. * 校验接口是否反复 */ if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null; // package to define proxy class in 代理类包名 int accessFlags = Modifier.PUBLIC | Modifier.FINAL; /* * Record the package of a non-public proxy interface so that the 记录非公共代理接口的程序包,以便在同一包中定义代理类。 验证所有非公共代理接口都在同一包中。 * proxy class will be defined in the same package. Verify that * all non-public proxy interfaces are in the same package. */ 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) { // if no non-public proxy interfaces, use com.sun.proxy package // public代理接口,应用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; /* * Generate the specified proxy class. 真正生成代理类的字节码文件的中央 */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { // 应用类加载器将代理类的字节码文件加载到JVM中 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the 这里的ClassFormatError示意(排除代理类生成代码中的谬误)提供给代理类创立的参数还有其余一些有效方面(例如,超出了虚拟机限度) * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); } } } //用户和本地C代码进行互操作的API,称为Java Native Interface (Java本地接口) private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
ProxyGenerator.generateProxyClass
咱们能够看到在ProxyClassFactory类的apply办法中可看出真正生成代理类字节码的中央是ProxyGenerator类中的generateProxyClass
package sun.misc; public class ProxyGenerator 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)); Files.createDirectories(var3); var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class"); } else { var2 = Paths.get(var0 + ".class"); } Files.write(var2, var4, new OpenOption[0]); return null; } catch (IOException var4x) { throw new InternalError("I/O exception saving generated file: " + var4x); } } }); } return var4; }
代理类
在Main函数中减少,将JDK动静代理生成的class文件保留到本地,保留门路com.sun.proxy
System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
关上生成的代理类
- 继承了Proxy类,实现了代理的接口,因为java不能多继承,这里曾经继承了Proxy类了,不能再继承其余的类,所以JDK的动静代理不反对对实现类的代理,只反对接口的代理。
- 提供了一个应用InvocationHandler作为参数的构造方法。
- 生成动态代码块来初始化接口中办法的Method对象,以及Object类的equals、hashCode、toString办法。
- 重写了Object类的equals、hashCode、toString,它们都只是简略的调用了InvocationHandler的invoke办法,即能够对其进行非凡的操作,也就是说JDK的动静代理还能够代理上述三个办法。
- 代理类实现代理接口的sayHello办法中,只是简略的调用了InvocationHandler的invoke办法,咱们能够在invoke办法中进行一些非凡操作,甚至不调用实现的办法,间接返回。
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//package com.sun.proxy;import com.example.offer.designmode.proxy.dynamicproxy.CatInterface;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy2 extends Proxy implements CatInterface { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy2(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 say() 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("com.example.offer.designmode.proxy.dynamicproxy.CatInterface").getMethod("say"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }}