一、 *** 模式
*** 模式是java23种设计模式常用的一种设计模式。 *** 模式是客户端不直接调用实际对象,而是通过调用 *** 对象来间接调用使用实际对象。为什么使用 *** 模式来间接调用使用实际对象,而不是直接使用实际对象呢?这里主要有两方面的考量:
出于安全、封装性的考量,不想直接使用实际对象使用实际对象比较麻烦现实生活中律师、房屋中介其实就是活生生的 *** 模式我们来看下 *** 模式的关系图:
java中 *** 模式分为静态 *** 和动态 *** 的不同实现
1、静态 *** 的实现:
public interface Subject { void test();}public class RealSubject implements Subject { @Override public void test() { System.out.println("this is RealSubject test"); }}public class ProxySubject implements Subject { Subject mSubject; public ProxySubject(Subject pSubject){ mSubject = pSubject; } @Override public void test() { if(mSubject != null){ mSubject.test(); } }}public class Client { public static void main(String[] args){ RealSubject realSubject = new RealSubject(); ProxySubject proxySubject = new ProxySubject(realSubject); proxySubject.test(); }}
通过上面的代码我们可以看出静态 *** 的优缺点:
优点: *** 类可以接受一个已经实现了Subject接口的对象,任何实现了Subject接口的对象都可以通过 *** 类进行 *** ,实现了通用型缺点:当接口增删改 *** ,那么 *** 类已得要跟着修改; *** 类的每个接口对象对应一个委托对象,如果委托对象很多, *** 类就会变得异常臃肿
2、动态 ***
动态 *** 有别用静态 *** ,它是通过要 *** 的类,动态的生成 *** 类。这样可以避免静态 *** 中 *** 类接口过多的问题。动态 *** 的实现方式是借助java.lang.Reflect.Proxy进行反射实现的,其步骤如下:a、编写一个委托类接口,对应的静态 *** 的Subject接口b、编写一个委托类接口的实现类,对应的是静态 *** 的RealSubjectc、创建动态 *** 类 *** 调用处理程序,实现InvocationHandler接口,并重写invoke *** d、在测试类中生成动态 *** 对象定义委托对象接口:
public interface Subject { void test();}
委托对象接口实现类:
public class RealSubject implements Subject { @Override public void test() { System.out.print("this is dynamic RealSubject test"); }}
动态 *** 类 *** 调用处理程序:
public class DynamicProxy implements InvocationHandler { Object mObj; public DynamicProxy(Object pObj){ mObj = pObj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; System.out.println("this is Dynamic proxy invode"); if(mObj != null){ result = method.invoke(mObj, args); } return result; }}
使用动态 *** :
public class Client { public static void main(String[] args){ RealSubject realSubject = new RealSubject(); DynamicProxy proxy = new DynamicProxy(realSubject); Subject subject = (Subject) Proxy.newProxyInstance( realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), proxy ); subject.test(); }}
二、动态 *** 原理
通过上面动态 *** 的使用,它看似并没有 *** 类,那么它是什么进入DynamicProxy的invoke *** 实现实际委托对象 *** 的调用呢?下面我们通过源码一步一步解析揭开它什么的面纱:动态 *** 使用了Proxy.newProxyInstance *** 动态创建 *** 类,我们看下newProxyInstance源码:
/**@params loader 用于从动态生成的class字节流中加载创建 *** 类@params interfaces 委托对象实现的接口列表@params h *** 类 *** 调用处理器@return 返回动态创建的 *** 类*/public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { //动态 *** 类 *** 调用处理程序即这里的h不能为空 Objects.requireNonNull(h); //委托对象的接口列表 final Class<?>[] intfs = interfaces.clone(); //android中移除了安全相关的校验 // Android-removed: SecurityManager calls /* final SecurityManager *** = System.getSecurityManager(); if (*** != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } */ /* * Look up or generate the designated proxy class. */ //动态生成class文件字节流,然后通过loader加载此字节流创建 *** 类class Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { // Android-removed: SecurityManager / permission checks. /* if (*** != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } */ //获取 *** 类的类构造对象 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; //如果class对象不可访问,则修改为可访问 if (!Modifier.isPublic(cl.getModifiers())) { // BEGIN Android-changed: Excluded AccessController.doPrivileged call. /* AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); */ cons.setAccessible(true); // END Android-removed: Excluded AccessController.doPrivileged call. } // 通过类构造器创建 *** 实现类并返回 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); } }
newProxyInstance动态创建 *** 类的步骤是:
校验 *** 类 *** 调用处理程序h不能为空动态生成 *** 类class文件格式字节流通过loader加载创建代表 *** 类的class对象根据 *** 类的构造器创建 *** 类返回动态创建生成的 *** 类怎么生成 *** 类class文件格式字节流的呢?我们先看下getProxyClass0 *** :
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 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 return proxyClassCache.get(loader, interfaces); }
通过上面的代码告诉我们委托对象能实现的接口数量不能超过65535,就是Short类型的更大值我们再看proxyCache.get的实现,其中proxyCache是WeakCache的实现对象:
//WeakCache.java/**@params key 此处是类加载器loader@params parameter 此处是 *** 类接口列表*/public V get(K key, P parameter) { //此处要求 *** 类接口不能为空 Objects.requireNonNull(parameter); expungeStaleEntries(); //生成CacheKey对象 Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level value***ap for the particular cacheKey //根据cachekey获取键值对value***ap, value***ap的key是接口列表的包装类,value是动态生成 *** 类的包装类 ConcurrentMap<Object, Supplier<V>> value***ap = map.get(cacheKey); if (value***ap == null) { ConcurrentMap<Object, Supplier<V>> oldValue***ap = map.putIfAbsent(cacheKey, value***ap = new ConcurrentHashMap<>()); if (oldValue***ap != null) { value***ap = oldValue***ap; } } // create subKey and retrieve the possible Supplier<V> stored by that // subKey from value***ap //根据 *** 类接口生成的key Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); //动态生成 *** 类的包装类 Supplier<V> supplier = value***ap.get(subKey); //生成动态 *** 类的工厂类 Factory factory = null; while (true) { //如果动态 *** 类包装类supplier不为空,则使用supplier 中的工厂类factory加载动态生成的class文件格式的 *** 类的字节流 if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance //此处是factory加载动态生成的class文件格式的 *** 类的字节流的实现 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 //如果动态生成 *** 类的工厂类为空,则创建新的工厂类 if (factory == null) { factory = new Factory(key, parameter, subKey, value***ap); } if (supplier == null) { //工厂类的包装类为空,则创建新的包装类supplier supplier = value***ap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory supplier = factory; } // else retry with winning supplier } else { //工厂类的包装类不为空,则替换包装类中的工作累 if (value***ap.replace(subKey, supplier, factory)) { // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // retry with current supplier supplier = value***ap.get(subKey); } } } }
由上面的代码,大概知道通过map来存储动态生成的 *** 类,其中key是接口的包装类,value是动态 *** 类的包装类。
key的生成是通过subKeyFactory,subKeyFactory是KeyFactory的实现类,其实现很简单,只是对 *** 类接口进行包装:
private static final class KeyFactory implements BiFunction<ClassLoader, Class<?>[], Object> { @Override public Object apply(ClassLoader classLoader, Class<?>[] interfaces) { switch (interfaces.length) { case 1: return new Key1(interfaces[0]); // the most frequent case 2: return new Key2(interfaces[0], interfaces[1]); case 0: return key0; default: return new KeyX(interfaces); } } }private static final class Key1 extends WeakReference<Class<?>> { private final int hash; Key1(Class<?> intf) { super(intf); this.hash = intf.hashCode(); } @Override public int hashCode() { return hash; } @Override public boolean equals(Object obj) { Class<?> intf; return this == obj || obj != null && obj.getClass() == Key1.class && (intf = get()) != null && intf == ((Key1) obj).get(); } }
其他key1、keyx不展开说明
value是生成动态 *** 类的包装类,此包装类是实现了Supplier接口的Factory类,通过Factory的get *** 动态生成 *** 类:
@Override public synchronized V get() { // serialize access // re-check //从map中获取已经生成的动态 *** 类的包装类 Supplier<V> supplier = value***ap.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 { //通过valueFactory的apply *** 生成动态 *** 类 value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { if (value == null) { // remove us on failure value***ap.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 (value***ap.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; }
这里核心的实现是valueFactory的apply *** ,valueFactory是ProxyClassFactory的实现类,我们来看下ProxyClassFactory的apply *** ,看其是怎么实现生成动态 *** 类的:
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); //获取 *** 类接口的class对象,并校验是否是接口,如果不是则抛出错误 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. */ 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 the default package. proxyPkg = ""; } { // Android-changed: Generate the proxy directly instead of calling // through to ProxyGenerator. //获取 *** 类接口的 *** 列表,并进行排序和返回类型校验 List<Method> methods = getMethods(interfaces); Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SU *** YPE); validateReturnTypes(methods); //获取 *** 类别的异常列表 List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods); // *** 列表转为 *** 数组 Method[] methodsArray = methods.toArray(new Method[methods.size()]); //异常列表转为异常数组 Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]); /* * Choose a name for the proxy class to generate. */ //生成 *** 类唯一名称 long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg + proxyClassNamePrefix + num; //根据类名、接口、类加载器、 *** 列表、异常列表,按照class文件格式先生成字节流,再生成动态 *** 类 return generateProxy(proxyName, interfaces, loader, methodsArray, exceptionsArray); } }
//native *** ,其实现原理是根据类名、接口、类加载器、 *** 列表、异常列表,按照class文件格式先生成字节流,再生成动态 *** 类
@FastNativeprivate static native Class<?> generateProxy(String name, Class<?>[] interfaces, ClassLoader loader, Method[] methods, Class<?>[][] exceptions);
按照这样的流程,我们可以总结动态 *** 的原理如下:1、根据 *** 类接口先得到 *** 类的类全限名、 *** 列表、异常列表2、根据步骤1中的类全限名、 *** 列表、异常列表、接口列表生成class文件格式的字节流,其中 *** 的实现会最终调用InvoationHanlder的invoke *** 3、使用类加载器加载步骤2中的字节流,创建生成动态 *** 类对象4、使用步骤3中创建生成的 *** 类对象