番外篇,jdk自带动态代理源码分析

之前和同学聊起代理模式,顺嘴提到了动态代理,就顺便看了一下源码,话不多说,开始分析,和之前一样为了方便理解,我会直接在代码中注释

这是一段很常见的动态代理代码,TestInterface是一个接口,里面只有一个test方法,TestInterfaceImpl类实现了TestInterface接口,代码也比较简单,我就不全部贴出来了

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Test implements InvocationHandler {
   

    public  TestInterface ti;

    public Object newProxyInstance(TestInterface ti) {
   
        this.ti = ti;
        //重点
        return Proxy.newProxyInstance(ti.getClass().getClassLoader(), ti.getClass().getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
        System.out.println("执行方法前的操作");
        if(method.getName().equals("test"))
        {
   
            ti.test();
        }
        System.out.println("执行方法后的操作");
        return null;
    }

    public static void main(String[] args) {
   
        Test test =new Test ();
        TestInterface ti = (TestInterface)test.newProxyInstance(new TestInterfaceImpl());
        ti.test();
    }
}

重点是Proxy.newProxyInstance方法

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h) {
   
        //若传入的动态代理类为空抛出异常
        Objects.requireNonNull(h);
		//获取当前系统的安全检查器
		//因为这里会进行类加载和io操作,需要进行安全检查
        final Class<?> caller = System.getSecurityManager() == null
                                    ? null
                                    : Reflection.getCallerClass();

        /*
         * Look up or generate the designated proxy class and its constructor.
         */
         //关键方法
        Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
		//此处只是调用Constructor的newInstance方法
		//把动态代理对象传入,调用对应的构造方法
		//返回一个动态代理后的实体类
		//意义不大,这里就不多介绍
        return newProxyInstance(caller, cons, h);
    }

进入关键方法getProxyConstructor

private static Constructor<?> getProxyConstructor(Class<?> caller,
                                                      ClassLoader loader,
                                                      Class<?>... interfaces)
    {
   
        //判断需要代理的接口是否为多个,进行简单转换
        //if else内容几乎一致,就只对前面的if内容进行分析,不再赘述
        if (interfaces.length == 1) {
   
            Class<?> intf = interfaces[0];
            //判断是否需要进行安全检查
            if (caller != null) {
   
                checkProxyAccess(caller, loader, intf);
            }
            //重点方法,我会进行单独讲解
            return proxyCache.sub(intf).computeIfAbsent(
                loader,
                (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
            );
        } else {
   
            // interfaces cloned
            final Class<?>[] intfsArray = interfaces.clone();
            if (caller != null) {
   
                checkProxyAccess(caller, loader, intfsArray);
            }
            final List<Class<?>> intfs = Arrays.asList(intfsArray);
            return proxyCache.sub(intfs).computeIfAbsent(
                loader,
                (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
            );
        }
    }

这段代码相当优雅,把lanbda表达式写的出神入化(但是我不建议大家平时这样写,可读性极差,我自己看这段代码蒙了有一会)

return proxyCache.sub(intf).computeIfAbsent(
                loader,
                (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
            );

首先我们来看computeIfAbsent方法

public V computeIfAbsent(ClassLoader cl,
                             BiFunction<
                                 ? super ClassLoader,
                                 ? super CLV,
                                 ? extends V
                                 > mappingFunction)

lanbda表达式推导的就是BiFunction接口的方法,进入BiFunction接口

public interface BiFunction<T, U, R> {
   
    R apply(T t, U u);
    。。。省略。。。
}

问题来了,我们可以把lanbda表达式写成下面的代码

R apply(T ld, U clv){
   
	return new ProxyBuilder(ld, clv.key()).build();
}

然后通过类型推导(根据computeIfAbsent方法进行推导)将代码推导为

R apply(ClassLoader ld, U clv){
   
	return new ProxyBuilder(ld, clv.key()).build();
}

再根据sub方法,和AbstractClassLoaderValue,Sub类进行进一步的推导


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值