代理模式是java23种设计模式常用的一种设计模式。代理模式是客户端不直接调用实际对象,而是通过调用代理对象来间接调用使用实际对象。为什么使用代理模式来间接调用使用实际对象,而不是直接使用实际对象呢?这里主要有两方面的考量:
出于安全、封装性的考量,不想直接使用实际对象使用实际对象比较麻烦现实生活中律师、房屋中介其实就是活生生的代理模式我们来看下代理模式的关系图:
java中代理模式分为静态代理和动态代理的不同实现
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接口的对象都可以通过代理类进行代理,实现了通用型缺点:当接口增删改方法,那么代理类已得要跟着修改;代理类的每个接口对象对应一个委托对象,如果委托对象很多,代理类就会变得异常臃肿
动态代理有别用静态代理,它是通过要代理的类,动态的生成代理类。这样可以避免静态代理中代理类接口过多的问题。动态代理的实现方式是借助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 sm = System.getSecurityManager(); if (sm != 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 (sm != 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() { 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 valuesMap for the particular cacheKey //根据cachekey获取键值对valuesMap, valuesMap的key是接口列表的包装类,value是动态生成代理类的包装类 ConcurrentMap由上面的代码,大概知道通过map来存储动态生成的代理类,其中key是接口的包装类,value是动态代理类的包装类。
key的生成是通过subKeyFactory,subKeyFactory是KeyFactory的实现类,其实现很简单,只是对代理类接口进行包装:
private static final class KeyFactory implements BiFunction[], 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> { 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 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 { //通过valueFactory的apply方法生成动态代理类 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 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; } 这里核心的实现是valueFactory的apply方法,valueFactory是ProxyClassFactory的实现类,我们来看下ProxyClassFactory的apply方法,看其是怎么实现生成动态代理类的:
public Class> apply(ClassLoader loader, Class>[] interfaces) { Map, 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 methods = getMethods(interfaces); Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE); validateReturnTypes(methods); //获取方法类别的异常列表 List[]> 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中创建生成的代理类对象
版权声明:我们致力于保护作者版权,注重分享,被刊用文章【java动态代理原理(动态代理原理解析)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!;
工作时间:8:00-18:00
客服电话
电子邮件
beimuxi@protonmail.com
扫码二维码
获取最新动态
