Spring学习第二天Aop_invoke的代理对象生成解析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34629467/article/details/79417946

我还是事先声明我目前写的都是我的一些理解,仅仅作为我的笔记作为参考!

今天的主要内容就是解析动态代理中的newProxyInstance 和 invoke方法

第一部分:newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h):这个方法主要就是获取代理对象,其实就是委托类的实例,再进一步就是委托类拥有真实业务类的引用,从而这个代理类可以代替真实业务类处理业务逻辑;

    ClassLoader:类加载器的作用是什么呢?顾名思义,就是加载类文件,就是.class字节码文件(主要由8位字节码组成),这个部分可以详细的去学习JVM虚拟机;我的通俗理解就是使用这个类加载器对象可以去加载类对象;

    Class<?>[]:类,这个类是有一个private的私有构造方法,它是由JVM进行实例化的,大概所有的类都可以作为它的实例,比如User.class,可以是它的一个实例,这个Class的组成呢? 我们通过一些元或者初始化的东西来描述一个类:

        包名、类名或者接口、修饰符(类的修饰符、接口的修饰符、属性的修饰符、方法的修饰符)、

        方法以及方法参数、成员属性、

        注解等等;

    InvocationHandler:顾名思义: 调用处理器接口,只有一个invoke的方法;

第二部分:invoke(target,args)方法:

    target: 方法名

    args: 传入方法名中的参数

    综合上面的因素:我们推断: jvm的类加载器加载某一个类(真实业务类),因为加载了这个类所以我们就可以获得这个类的所有的信息(方法、属性啊),然后通过指定方法(这个类中的特定业务逻辑方法)以及参数就可以进行调用了;

其实还是没有理解到代理对象如何执行到业务方法的?然后我想理解的是invoke这个方法的底层:

  1. Object newProxyInstance(ClassLoader loader,  
  2.                       Class<?>[] interfaces,  
  3.                       InvocationHandler h) 

首先我们看下这个方法的实现:在获得代理实例方法里面有下面这个方法:

     Class cl = getProxyClass(loader, interfaces);//这个方法主要就是获得代理的真实的类的对象,这个真实的类实现了至少一个接口,这个接口主要是我们自定义的(业务逻辑抽象接口),

  1. / 加载目标类实现的接口到内存中  
  2.         interfaceClass = Class.forName(interfaceName, false, loader);  

加载相应的接口到内存中,其实也就是加载.class文件中的Class对象到内存中,

  1. // 把目标类实现的接口名称作为缓存(Map)中的key  
  2.     Object key = Arrays.asList(interfaceNames);  
这几个步骤是将第一次生成的Class类中的信息缓存起来,就是存到内存中,下次用的时候直接取,

  1. Map cache;  
  2.       
  3.     synchronized (loaderToCache) {  
  4.         // 从缓存中获取cache  
  5.         cache = (Map) loaderToCache.get(loader);  
  6.         if (cache == null) {  
  7.         // 如果获取不到,则新建地个HashMap实例  
  8.         cache = new HashMap();  
  9.         // 把HashMap实例和当前加载器放到缓存中  
  10.         loaderToCache.put(loader, cache);  
  11.         }  

最关键的是这个一步:

  1. try {  
  2.         // 中间省略了一些代码 .......  
  3.           
  4.         // 这里就是动态生成代理对象的最关键的地方  
  5.         byte[] proxyClassFile = ProxyGenerator.generateProxyClass(  
  6.             proxyName, interfaces);  
  7.         try {  
  8.             // 根据代理类的字节码生成代理类的实例  
  9.             proxyClass = defineClass0(loader, proxyName,  
  10.             proxyClassFile, 0, proxyClassFile.length);  
  11.         } catch (ClassFormatError e) {  
  12.             throw new IllegalArgumentException(e.toString());  
  13.         }  
  14.         }  
  15.         // add to set of all generated proxy classes, for isProxyClass  
  16.         proxyClasses.put(proxyClass, null);  
  17.   
  18.     }   

我们是通过代理生成器来生成代理类的字节码,(注意代理类是含有真实业务的类的引用的),

又当我们获取到一个类的字节码的时候,有一个方法可以直接获取这个类的实例:

defineClass0(loader,proxyName,proxyClassFile,0,proxyClassFile.length);




    




展开阅读全文

没有更多推荐了,返回首页