jdk动态代理源码解析

我们一直用jdk动态代理,还没有深入进去看一下,那么这篇文章就来看一下他是怎么创建动态代理的:


    UserService userService = new UserServiceImpl();
		
		UserService proxy = (UserService) Proxy.newProxyInstance(
				Thread.currentThread().getContextClassLoader(), 
				userService.getClass().getInterfaces(), 
				new InvocationHandler() {
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("before");
						method.invoke(userService,args);
						System.out.println("after");
						return null;
					}
				});
		
		proxy.add();

以上就是我们的示例代码,接下来我们就开始进入动态代理的创建过程:

 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);

        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
			//根据构造函数的参数选择一个构造函数,默认是InvocationHandler
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
            //通过反射实例化代理类
            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);
        }
    }

在这个方法中最重要的三件事就是:
1、利用我们传入的类加载器和接口创建代理类的class对象
2、选择一个构造函数
3、根据构造函数实例化对象

private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        return proxyClassCache.get(loader, interfaces);
    }

首先会从代理类的缓存中查找是否创建过当前class对象,有的话直接返回,否则再创建:

public V get(K key, P parameter) {
		//对接口进行非空判断
        Objects.requireNonNull(parameter);
		//清除一些失效的Entry
        expungeStaleEntries();
		//将当前类加载器封装成一个cacheKey
        Object cacheKey = CacheKey.valueOf(key, refQueue);

        // 从缓存中查找由当前类加载器加载的class对象
        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
        //如果没有找到,说明没有找到,然后通过原子操作为当前类加载器创建一个map
        if (valuesMap == null) {
            ConcurrentMap<Object, Supplier<V>> oldValuesMap
                = map.putIfAbsent(cacheKey,
                                  valuesMap = new ConcurrentHashMap<>());
            if (oldValuesMap != null) {
                valuesMap = oldValuesMap;
            }
        }

        // 通过类加载器和接口创建一个key用来定位class对象
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        //根据key查找
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;
		//如果找到了对应的class对象就直接返回,否则创建一个
        while (true) {
        	//如果不为null,说明缓存中有,直接返回class对象
            if (supplier != null) {
                // supplier might be a Factory or a CacheValue<V> instance
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            // 创建一个class对象
            if (factory == null) {
                factory = new Factory(key, parameter, subKey, valuesMap);
            }
			//通过原子操作将当前创建的class对象放到集合中
            if (supplier == null) {
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    supplier = factory;
                }
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    //替换旧的值
                    supplier = factory;
                } else {
                    // 替换失败使用旧的值
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }

针对不同的类加载器会有一个Map用来存放它加载的class对象,如果缓存中有,那么直接返回,没有就会创建一个然后放到缓存里面,接下来我们看一下class对象是如何被获取到的:

public synchronized V get() { // serialize access
            // 在验证一次
            Supplier<V> supplier = valuesMap.get(subKey);
            if (supplier != this) {
                // 如果不相同返回null
                return null;
            }
            // else still us (supplier == this)

            // create new value
            V value = null;
            try {
            	//创建class对象
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { 
                	//如果创建失败移除这个元素
                    valuesMap.remove(subKey, this);
                }
            }
            // the only path to reach here is with non-null value
            assert value != null;

            // 将当前值封装成一个缓存的值
            CacheValue<V> cacheValue = new CacheValue<>(value);

            //放到map里面
            reverseMap.put(cacheValue, Boolean.TRUE);

            // try replacing us with CacheValue (this should always succeed)
            if (!valuesMap.replace(subKey, this, cacheValue)) {
                throw new AssertionError("Should not reach here");
            }

            // successfully replaced us with new CacheValue -> return the value
            // wrapped by it
            return value;
        }
    }

在这里面最重要的方法就是apply:

 public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
			
            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            //遍历所有的接口
            for (Class<?> intf : interfaces) {
                //重新创建当前接口的class对象
                Class<?> interfaceClass = null;
                try {
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
                ...
            }

            String proxyPkg = null;     // package to define proxy class in
            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) {
                // if no non-public proxy interfaces, use com.sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            //为当前代理类生成一个编号
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            //生成代理类字节码文件
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
            	//根据字节码文件创建代理class对象
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
              
                throw new IllegalArgumentException(e.toString());
            }
        }

这个方法很长,我们关注的就只有两件事:
1、生成代理类字节码文件
2、根据字节码文件创建代理class对象
接下来就是通过反射实例化对象了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值