JDK1.8 动态代理机制及源码解析
来源:互联网 发布:动态图修改软件 编辑:程序博客网 时间:2024/06/06 01:10
静态代理
核心思想:代理对象通过持有需要被代理类的实例,实现代理方式。参考链接: http://www.cnblogs.com/mengdd/archive/2013/01/30/2883468.html
动态代理
a) jdk 动态代理 Proxy,
核心思想:通过实现被代理类的所有接口,生成一个字节码文件后构造一个代理对象,通过持有反射构造被代理类的一个实例,再通过invoke反射调用被代理类实例的方法,来实现代理。
缺点:被代理类必须实现一个或多个接口
参考链接:http://rejoy.iteye.com/blog/1627405
源码解析:见第四部分
cglib 动态代理
核心思想:通过生成子类字节码实现,代理类为每个委托方法都生成两个方法,以add方法为例,一个是重写的add方法,一个是CGLIB$add$0方法,该方法直接调用委托类的add方法; 底层:使用一个小而快的字节码处理框架ASM(Java字节码操控框架),来转换字节码并生成新的类 缺点:不能代理final修饰的类, 参考链接:http://blog.csdn.net/yakoo5/article/details/9099133/
AOP实现机制
a. 实现方式:cglib 和 jdk自带的Proxy实现 b. 策略: 1)如果是有接口声明的类进行AOP 时,spring调用的是Java.lang.reflection.Proxy 类来做处理 2)如果是没有接口声明的类时, spring通过cglib包和内部类来实现 c.配置: <aop:aspectj-autoproxy proxy-target-class="true" />配置了这句话的话就会强制使用cglib代理。 默认就是false
JDK动态代理Demo
//业务类接口public interface MyBusinessInterface{ public void processBusiness();}//业务实现类public class MyBusinessInterfaceImpl implements MyBusinessInterface { public void processBusiness() { System.out.println("processing business....."); }}//被代理对象调用处理程序,必须实现InvocationHandler接口public class MyInvocationHandler implements InvocationHandler { //所代理的真实对象 private Object target = null; //构造器,用于传入所代理的真实对象 MyInvocationHandler(Object target){ this.target = target; } //需要我们实现具体业务的地方 //proxy: 所生成代理类实例 //method: 指代的是我们所要调用真实对象的某个方法的Method对象 //args: 指代的是调用真实对象某个方法时接受的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("You can do something here before process your business"); //调用目标对象的方法 Object result = method.invoke(target, args); System.out.println("You can do something here after process your business"); //返回处理结果 return result; }}//测试用例public class Test { public static void main(String[] args) { //被代理真实对象 MyBusinessInterfaceImpl bpimpl = new MyBusinessInterfaceImpl(); //被代理对象调用处理程序,需传入被代理对象 MyInvocationHandler handler = new MyInvocationHandler(bpimpl); //生成代理类实例 MyBusinessInterface bp = (MyBusinessInterface)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); //调用processBusiness bp.processBusiness(); }}
JDK1.8动态代理源码解析
Proxy解析
//代理类public class Proxy implements java.io.Serializable { private static final long serialVersionUID = -2222568056686623797L; //代理类构造函数的参数类型 private static final Class<?>[] constructorParams = { InvocationHandler.class }; //代理类缓存 private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); //此代理实例的调用处理程序。 protected InvocationHandler h; private Proxy() { } //代理类构造函数,参数类型:constructorParams所指定 protected Proxy(InvocationHandler h) { Objects.requireNonNull(h); this.h = h; } //获取目标代理类Class对象,需传入类加载器loader对象和被代理类实现接口数组interfaces随想 @CallerSensitive public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces) throws IllegalArgumentException{ //拷贝接口数组 final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { //校验代理类的访问问权限 checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } //获取代理类Class对象 return getProxyClass0(loader, intfs); } //校验代理类的访问问权限,这一块比较底层,我也不明白 private static void checkProxyAccess(Class<?> caller, ClassLoader loader, Class<?>... interfaces){ SecurityManager sm = System.getSecurityManager(); if (sm != null) { //获取调用者类的类加载器 ClassLoader ccl = caller.getClassLoader(); if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) { sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); } ReflectUtil.checkProxyPackageAccess(ccl, interfaces); } } //获取代理类的Clas对象 private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } //如果存在给定接口的给定装入器定义的代理类存在,则只返回缓存的副本; //否则,它将通过proxyclassfactory创建代理类 //jdk1.8后收敛到这里 生成代理类字节码过程: ProxyClassFactory中了 return proxyClassCache.get(loader, interfaces); } //用于带有0个实现接口的代理类的key键值 private static final Object key0 = new Object(); /* * Key1 and Key2 are optimized for the common use of dynamic proxies * that implement 1 or 2 interfaces. */ /* * a key used for proxy class with 1 implemented interface */ //用于带有1个实现接口的代理类的key键值 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(); } } // //用于带有2个实现接口的代理类的key键值 private static final class Key2 extends WeakReference<Class<?>> { private final int hash; //弱引用对象:存放第二个接口类对象 private final WeakReference<Class<?>> ref2; Key2(Class<?> intf1, Class<?> intf2) { super(intf1); hash = 31 * intf1.hashCode() + intf2.hashCode(); ref2 = new WeakReference<Class<?>>(intf2); } @Override public int hashCode() { return hash; } @Override public boolean equals(Object obj) { Class<?> intf1, intf2; return this == obj || obj != null && obj.getClass() == Key2.class && (intf1 = get()) != null && intf1 == ((Key2) obj).get() && (intf2 = ref2.get()) != null && intf2 == ((Key2) obj).ref2.get(); } } // 这里用于带有>=3个实现接口的代理类的key键值(可以当实现任意数目接口的代理的key) private static final class KeyX { //接口数组对象的hash值 private final int hash; //弱引用对象数组:存放表示接口的类对象数组 private final WeakReference<Class<?>>[] refs; @SuppressWarnings("unchecked") KeyX(Class<?>[] interfaces) { hash = Arrays.hashCode(interfaces); //构造一个弱引用对象数组 refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { refs[i] = new WeakReference<>(interfaces[i]); } } @Override public int hashCode() { return hash; } @Override public boolean equals(Object obj) { return this == obj || obj != null && obj.getClass() == KeyX.class && equals(refs, ((KeyX) obj).refs); } private static boolean equals(WeakReference<Class<?>>[] refs1, WeakReference<Class<?>>[] refs2) { //长度是否相等 if (refs1.length != refs2.length) { return false; } //弱引用对象数组内接口类是否相同 for (int i = 0; i < refs1.length; i++) { Class<?> intf = refs1[i].get(); if (intf == null || intf != refs2[i].get()) { return false; } } return true; } } //将接口数组映射到一个最佳键的函数,其中表示接口的类对象为弱引用。 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 ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { //所有代理类名称的前缀 private static final String proxyClassNamePrefix = "$Proxy"; //用于生成唯一代理类名称的下一个数字 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) { //验证intf接口类Class对象是否为给定的classloder解析的 Class<?> interfaceClass = null; try { //指定类加载器获取接口类class对象, 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"); } /* * 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; //定义代理类的修饰符:public和final类型 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)) { //不是public修饰符 //则定义代理类的修饰符符:final accessFlags = Modifier.FINAL; //获取接口类名称,如:com.text.MyInterface String name = intf.getName(); int n = name.lastIndexOf('.'); //获取包名,如:com.text String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { //获取包名称 proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { //interfaces含有来自不同包的非公共接口,抛错 throw new IllegalArgumentException( "non-public interfaces from different packages"); } } } if (proxyPkg == null) { //如果没有非公开的代理接口,使用com.sun.proxy作为包名称 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } //选择要生成的代理类的名称。 long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; //真正生成指定的代理类字节码的地方 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { //生成Calss对象 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * 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()); } } } //生成代理类对象 @CallerSensitive public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException { //调用处理程序不能为空 Objects.requireNonNull(h); //拷贝接口数组对象 final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } //查找或生成指定的代理类。 Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. * 调用指定的调用处理程序的构造函数 */ try { if (sm != null) { //校验新代理类的权限 checkNewProxyPermission(Reflection.getCallerClass(), cl); } //获取代理类构造函数,参数类型必须为InvocationHandler final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; //构造函数不是public,则设置当前构造函数为访问权限 if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //调用构造函数构造代理类实例,入参数为‘调用处理程序’的实例,看到这里应该就明白jdk怎么实现动态代理的吧! 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); } } private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ReflectUtil.isNonPublicProxyClass(proxyClass)) { //调用者类加载器 ClassLoader ccl = caller.getClassLoader(); //代理类的类加载器 ClassLoader pcl = proxyClass.getClassLoader(); // do permission check if the caller is in a different runtime package // of the proxy class //获取代理类的包名 int n = proxyClass.getName().lastIndexOf('.'); String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n); //获取调用者包名 n = caller.getName().lastIndexOf('.'); String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n); //类加载不相同或包名不相同,校验权限 if (pcl != ccl || !pkg.equals(callerPkg)) { sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg)); } } } } public static boolean isProxyClass(Class<?> cl) { return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl); } @CallerSensitive public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { //验证该对象实际上是否为上一个代理实例。 if (!isProxyClass(proxy.getClass())) { throw new IllegalArgumentException("not a proxy instance"); } final Proxy p = (Proxy) proxy; final InvocationHandler ih = p.h; if (System.getSecurityManager() != null) { Class<?> ihClass = ih.getClass(); Class<?> caller = Reflection.getCallerClass(); if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), ihClass.getClassLoader())) { ReflectUtil.checkPackageAccess(ihClass); } } return ih; } private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);}
WeakCache类解析 ####
//用处存放final class WeakCache<K, P, V> { private final ReferenceQueue<K> refQueue = new ReferenceQueue<>(); // the key type is Object for supporting null key //Map<类加载器,Map<接口数组对象key,代理类工厂Factory或代理类包装对象LookupValue> private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>(); //存放当前key所对应的实例是否已经生成 private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap<>(); //生成key的工厂(对应上面的Key1-X类) private final BiFunction<K, P, ?> subKeyFactory; //生成value(代理类工厂,对应上面的ProxyClassFactory类) private final BiFunction<K, P, V> valueFactory; //构造方法,指定key和value工厂 public WeakCache(BiFunction<K, P, ?> subKeyFactory, BiFunction<K, P, V> valueFactory) { this.subKeyFactory = Objects.requireNonNull(subKeyFactory); this.valueFactory = Objects.requireNonNull(valueFactory); } //获取缓存值, public V get(K key, P parameter) { //parameter不能weinull Objects.requireNonNull(parameter); //删除老节点 expungeStaleEntries(); Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level valuesMap for the particular cacheKey ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { //添加cacheKey - ConcurrentMap<Object, Supplier<V>对象到map中 ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } //利用subKeyFactory生成subKey Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); //获取valuesMap中subKey所对应的值,此时为cachevalue <V>实例(步骤1:cachevalue <V>实例的来源) Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; while (true) { if (supplier != null) { //步骤1:supplier可能是一个工厂对象或一个cachevalue <V>实例 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) { //构造一个工厂对象(步骤1:工厂对象的来源) factory = new Factory(key, parameter, subKey, valuesMap); } // if (supplier == null) { //factory添加在valuesMap中 supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // 添加成功,则factory赋值给supplier,此时supplier为一个工厂对象 supplier = factory; } // else retry with winning supplier //失败则重试 } else { //将valuesMap中subKey所对应的值替换为factory 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); } } } } /** * Checks whether the specified non-null value is already present in this * {@code WeakCache}. The check is made using identity comparison regardless * of whether value's class overrides {@link Object#equals} or not. * * @param value the non-null value to check * @return true if given {@code value} is already cached * @throws NullPointerException if value is null */ public boolean containsValue(V value) { Objects.requireNonNull(value); expungeStaleEntries(); return reverseMap.containsKey(new LookupValue<>(value)); } /** * Returns the current number of cached entries that * can decrease over time when keys/values are GC-ed. */ public int size() { expungeStaleEntries(); return reverseMap.size(); } private void expungeStaleEntries() { CacheKey<K> cacheKey; while ((cacheKey = (CacheKey<K>)refQueue.poll()) != null) { cacheKey.expungeFrom(map, reverseMap); } } /** * A factory {@link Supplier} that implements the lazy synchronized * 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 //校验是否为同一个 Supplier<V> supplier = valuesMap.get(subKey); if (supplier != this) { //在我们等待的时候,可能某些值已经被替换或则删除,返回null让WeakCache.get()再次循环获取 return null; } //创建一个新值 V value = null; try { //调用valueFactory的applay方法生成一个新值 value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { if (value == null) { //如果生成失败,从valuesMap中删除值 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); //尝试更换我们cachevalue(这应该总是成功的)此时 if (valuesMap.replace(subKey, this, cacheValue)) { // 放在reversemap reverseMap.put(cacheValue, Boolean.TRUE); } else { throw new AssertionError("Should not reach here"); } //成功取代当前工厂对象为一个新的CacheValue(包裹着我们的需要对象:代理类) return value; } } //Value接口 private interface Value<V> extends Supplier<V> {} //值对象:包裹着我们的需要对象:代理类 private static final class LookupValue<V> implements Value<V> { private final V value; LookupValue(V value) { this.value = value; } @Override public V get() { return value; } @Override public int hashCode() { return System.identityHashCode(value); // compare by identity } @Override public boolean equals(Object obj) { return obj == this || obj instanceof Value && this.value == ((Value<?>) obj).get(); // compare by identity } } /** * A {@link Value} that weakly references the referent. */ private static final class CacheValue<V> extends WeakReference<V> implements Value<V> { private final int hash; CacheValue(V value) { super(value); this.hash = System.identityHashCode(value); // compare by identity } @Override public int hashCode() { return hash; } @Override public boolean equals(Object obj) { V value; return obj == this || obj instanceof Value && // cleared CacheValue is only equal to itself (value = get()) != null && value == ((Value<?>) obj).get(); // compare by identity } } private static final class CacheKey<K> extends WeakReference<K> { // a replacement for null keys private static final Object NULL_KEY = new Object(); static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) { return key == null // null key means we can't weakly reference it, // so we use a NULL_KEY singleton as cache key ? NULL_KEY // non-null key requires wrapping with a WeakReference : new CacheKey<>(key, refQueue); } private final int hash; private CacheKey(K key, ReferenceQueue<K> refQueue) { super(key, refQueue); this.hash = System.identityHashCode(key); // compare by identity } @Override public int hashCode() { return hash; } @Override public boolean equals(Object obj) { K key; return obj == this || obj != null && obj.getClass() == this.getClass() && // cleared CacheKey is only equal to itself (key = this.get()) != null && // compare key by identity key == ((CacheKey<K>) obj).get(); } void expungeFrom(ConcurrentMap<?, ? extends ConcurrentMap<?, ?>> map, ConcurrentMap<?, Boolean> reverseMap) { // removing just by key is always safe here because after a CacheKey // is cleared and enqueue-ed it is only equal to itself // (see equals method)... ConcurrentMap<?, ?> valuesMap = map.remove(this); // remove also from reverseMap if needed if (valuesMap != null) { for (Object cacheValue : valuesMap.values()) { reverseMap.remove(cacheValue); } } } }}
Proxy实际生成的代理类
import dynamic.proxy.UserService; import java.lang.reflect.*; public final class $Proxy11 extends Proxy implements UserService { // 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例 public $Proxy11(InvocationHandler invocationhandler) { super(invocationhandler); } public final boolean equals(Object obj) { try { return ((Boolean)super.h.invoke(this, m1, new Object[] { obj })).booleanValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } /** * 这个方法是关键部分 */ public final void add() { try { // 实际上就是调用MyInvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法,第二个问题就解决了 super.h.invoke(this, m3, null); return; } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return ((Integer)super.h.invoke(this, m0, null)).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)super.h.invoke(this, m2, null); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } private static Method m1; private static Method m3; private static Method m0; private static Method m2; // 在静态代码块中获取了4个方法:Object中的equals方法、UserService中的add方法、Object中的hashCode方法、Object中toString方法 static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); } catch(NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch(ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } } }
阅读全文
0 0
- JDK1.8 动态代理机制及源码解析
- 动态代理源码解析
- Hadoop源码解析之java动态代理机制
- 动态代理[JDK]机制解析
- JDK动态代理源码解析
- Retrofit源码解析-动态代理
- Retrofit源码解析-动态代理
- jdk动态代理源码解析
- HashMap 源码解析(JDK1.8)
- BlockingQueue源码解析jdk1.8
- JDK1.8 StampedLock源码解析
- ArrayList源码解析(jdk1.8)
- Vector源码解析(jdk1.8)
- LinkedList源码解析(jdk1.8)
- jdk1.8----ArrayList源码解析
- jdk1.8 String源码解析
- 【Java】从源码分析动态代理机制
- Java代理机制及动态代理和CGLIB代理详解
- JAVA反射(2)
- Think PHP 5学习笔记
- JAVA反射(3)
- JAVA反射(4)
- 常用网址
- JDK1.8 动态代理机制及源码解析
- TCP协议以及其报头结构分析
- 腾讯笔试题--微信红包
- 递归删除一个文件夹
- JNI开发流程
- Spring 源码之 BeanDefinition阅读
- SpringMvc的DispatcherServlet和Control的线程安全问题
- DFS、栈、双向队列:CF264A- Escape from Stones
- NGUI 类皇室战争(CR)的滚动列表效果完整实现(四)