资讯专栏INFORMATION COLUMN

吃透动态代理,解密spring AOP源码(三)

Coding01 / 1090人阅读

摘要:对象什么时候被回收答可达性分析,当发现某个类不被引用,类会被回收类的生命周期与动态代理关系动态代理是没有源文件,直接生成字节码的,加载到上面的。

上节讲到动态代理生成的类为$Proxy0,但是在我们项目里面却不存在,实际我们是用了这个实现类调用了方法,想要知道这个问题,首先要理解类的完整生命周期.

类的完整生命周期

Java源文件:即我们在IDE里面写的.java文件

Java字节码:即编译器编译之后的.class文件(javac命令).备注:Java代码为何能够跨平台,和Java字节码技术是分不开的,这个字节码在windows,在linux下都是可以运行的

class对象:工程启动的时候classLoader类加载器会扫描这些字节码并加载到classLoader上面生成class对象,有了类对象,便可以new实例了。(class对象保存在方法区元空间JDK1.8)

卸载:垃圾回收,关于回收机制,算法有兴趣可以去了解。class对象什么时候被回收?答:可达性分析,当发现某个类不被引用,类会被回收

类的生命周期与动态代理关系

动态代理是没有Java源文件,直接生成Java字节码的,加载到JVM上面的。字节码来源于内存,比如tomcat的热加载就是从网络传输过来的。

既然是直接生成的Java字节码,是怎么生成的?从源码开始分析,从Proxy.newProxyInstance方法开始看。

Class cl = getProxyClass0(loader, intfs);这行代码生成了.class字节码并且生成了class对象,然后拿这个类对象获取构造函数,再newInstance,生成实例对象,是通过反射的机制。重点还是怎么生成.class字节码。


接下来apply()方法往下看

生成了字节码数组,从而生成了Java字节码,defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length)则是加载字节码文件,此方法为native方法,C语言方法,操作系统类库(C/C++/汇编)。

字节码文件的结构是如何的呢?我们把class文件生成出来并在反编译工具打开,这里就用到了源码里面的方法了。生成.class文件的代码如下:

public static void generateClass(String proxyName, Class[] paramArrayOfClass, Class clazz) throws IOException {
        byte[]  classFile=ProxyGenerator.generateProxyClass(
                proxyName, paramArrayOfClass);
        String path=clazz.getResource(".").getPath();
        System.out.println(path);
        FileOutputStream outputStream =null;
        outputStream = new FileOutputStream(path + proxyName + "p.class");
        outputStream.write(classFile);
        outputStream.flush();
        outputStream.close();
    }     

                           

在刚刚的动态代理测试类增加几行代码:

 public static void main(String[] args) throws IOException {
        // 代购公司C,负责代购所有产品
        DynamicProxyCompanyC proxy = new DynamicProxyCompanyC();
        // 日本有家A公司生产男性用品
        ManToolFactory dogToolFactory = new AManFactory();
        // 代购A公司的产品
        proxy.setFactory(dogToolFactory);
        // 创建A公司的代理对象
        ManToolFactory proxyObject = (ManToolFactory) proxy.getProxyInstance();
        // 代理对象完成代购男性用品
        proxyObject.saleManTool("D");
        System.out.println("--------------");
        // 日本有家B公司生产女性用品
        WomanToolFactory womanToolFactory = new BWomanFactory();
        // 代购B公司的产品
        proxy.setFactory(womanToolFactory);
        // 创建B公司的代理对象
        WomanToolFactory proxyObject1 = (WomanToolFactory) proxy.getProxyInstance();
        // 代理对象完成代购女性用品
        proxyObject1.saleWomanTool(1.8);
        //生成代理类的.class文件
        DynamicProxyCompanyC.generateClass(proxyObject1.getClass().getSimpleName(),
                womanToolFactory.getClass().getInterfaces(), womanToolFactory.getClass());
    }
    

根据打印出来的class文件路径打开并在反编译工具上打开

动态代理生成的类就是这个了,调用业务方法saleWomanTool实际上变成了这个h.invoke,而这个h是所有Proxy类里面含有的 protected InvocationHandler h;(源码可见),在用Proxy创建代理实例的时候已经传入过了。

所以调用方法saleWomanTool就有了前置增强和后置增强。到这里已经解开了动态代理的原理

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73693.html

相关文章

  • 吃透动态代理解密spring AOP源码(四)

    摘要:值得一提的是由于采用动态创建子类的方式生成代理对象,所以不能对目标类中的方法进行代理。动态代理中生成的代理类是子类,调试的时候可以看到,打开源码可看到实现了和也就实现方法。 前面讲到了动态代理的底层原理,接下来我们来看一下aop的动态代理.Spring AOP使用了两种代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理. ①JDK动态代理:使用JDK创建代理有一个限制...

    Codeing_ls 评论0 收藏0
  • 吃透动态代理解密spring AOP源码(二)

    摘要:紧接着上节,为了解决静态代理的问题,出现了动态代理,假设动态代理是一个代购公司,私有变量为动态生成的具体的真实对象,可代购对应的产品。这个注释是说提供个一个静态方法来创建代理类和代理实例,它也是所有由此方法创建的代理类的父类。 紧接着上节,为了解决静态代理的问题,出现了动态代理, 假设动态代理是一个代购公司,私有变量Object factory为动态生成的具体的真实对象,可代购对应的产...

    tianyu 评论0 收藏0
  • Spring AOP就是这么简单啦

    摘要:是一种特殊的增强切面切面由切点和增强通知组成,它既包括了横切逻辑的定义也包括了连接点的定义。实际上,一个的实现被拆分到多个类中在中声明切面我们知道注解很方便,但是,要想使用注解的方式使用就必须要有源码因为我们要 前言 只有光头才能变强 上一篇已经讲解了Spring IOC知识点一网打尽!,这篇主要是讲解Spring的AOP模块~ 之前我已经写过一篇关于AOP的文章了,那篇把比较重要的知...

    Jacendfeng 评论0 收藏0
  • 仿照 Spring 实现简单的 IOC 和 AOP - 下篇

    摘要:在上文中,我实现了一个很简单的和容器。比如,我们所熟悉的就是在这里将切面逻辑织入相关中的。初始化的工作算是结束了,此时处于就绪状态,等待外部程序的调用。其中动态代理只能代理实现了接口的对象,而动态代理则无此限制。 1. 背景 本文承接上文,来继续说说 IOC 和 AOP 的仿写。在上文中,我实现了一个很简单的 IOC 和 AOP 容器。上文实现的 IOC 和 AOP 功能很单一,且 I...

    AlexTuan 评论0 收藏0
  • 源码入手,一文带你读懂Spring AOP面向切面编程

    摘要:,,面向切面编程。,切点,切面匹配连接点的点,一般与切点表达式相关,就是切面如何切点。例子中,注解就是切点表达式,匹配对应的连接点,通知,指在切面的某个特定的连接点上执行的动作。,织入,将作用在的过程。因为源码都是英文写的。 之前《零基础带你看Spring源码——IOC控制反转》详细讲了Spring容器的初始化和加载的原理,后面《你真的完全了解Java动态代理吗?看这篇就够了》介绍了下...

    wawor4827 评论0 收藏0

发表评论

0条评论

Coding01

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<