jdk中的动态代理源码分析

前言

图片来自https://www.cnblogs.com/maohuidong/p/7992894.html

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对这个对象的访问。为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性

正题

首先,我们先来看下代理的实现,直接看Proxy类的介绍,如图所示,展示了创建代理的两种方式,第一种是先获取代理类,然后获取构造器,最后构造实例;第二种直接就是创建实例,调用更加的方便。

从代理的使用上发现了InvocationHandler、Class、Constructor等,反射构建实例不就是使用的这些东西吗?难道代理类也是用反射实现的?这里我们先不做回答,继续进行分析
Dynamic Proxy

我们先说下动态代理怎么来的哈!我们还有中代理叫静态代理,所谓静态代理就是将接口、实现类、代理类都手动的完成,比如:
 

public interface People {

    void position();

}

public class TeacherPeople implements People {

    @Override
    public void position() {
        System.out.println("teacher");
    }
}

public class PeopleProxy implements People {

    private People people = new TeacherPeople();

    @Override
    public void position() {
        System.out.println("before method");
        people.position();
        System.out.println("after method");
    }

    @Test
    public void proxyTest(){
        PeopleProxy  peopleProxy = new PeopleProxy();
        peopleProxy.position();
    }
}


如果我们每需要代理一个类就需要写一个代理就会产生很多的重复代理,因此就有了动态代理,在运行的过程中,动态的创建我们的代理类来完成相关的操作

整个动态代理的框架我在网上找了一个图,来自于:https://blog.csdn.net/qq_36285943/article/details/80152640

走进Proxy.newProxyInstance方法,先看前半部分的生成代理类:

那到底是怎样的生成的代理类,走进getProxyClass0查看:

我们先进入proxyClassCache看下这是个什么东西

proxyClassCache维护了一个subKeyFacory和valueFacory,且都是BiFunction类型的,我们分别看下KeyFactory和ProxyClassFactory

KeyFactory

ProxyClassFactory

apply的代码比较长,我筛选出几行关键的代码

@Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            //获取每个代理的接口的Class对象,存到set集合中
            for (Class<?> intf : interfaces) {
               
                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;
            //生成代理类的class文件,返回最后的Class
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
               
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

看完了WeakCache的构造,我们继续回到get方法:return proxyClassCache.get(loader, interfaces);

Factory与Supplier的关系也就是图中这样,其实也就是Factory

通过这一串的分析我们我们已经获取到了要生成代理的Factory,然后调用get方法去生成ProxyClass,生成的方法就是上面我们分析的ProxyClassFactory的apply方法

这里有点绕,各位一定要自己进入代码查看分析,通过一连串的方法我们就拿到了代理类的Class对象,也就是Proxy。newinstance的前部分 ,然后我们再来看后半部分,后半部分就简单多了。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值