#Java#动态代理,大概是Java里最难弄懂的知识点了吧( 二 )


它们都对应Java中的一种设计模式 , 叫装饰设计模式:

  • 装饰者:缓冲字符流、刘小爱就是装饰者
  • 被装饰者:字符流、洛天依就是被装饰者
  • 装饰者将被装饰者的方法增强了
该设计模式其实和Java中的继承很相似:
  • 父类就相当于被装饰者
  • 子类就相当于装饰者
  • 子类重写方法就是在增强父类的方法
只不过该设计模式在代码层面比继承更具有拓展性 。
学习了装饰设计模式 , 接着开始动态代理的学习 。
二、动态代理装饰设计模式和动态代理很相似 , 它是一种静态代理 。
如何理解静态和动态?
  • 静态:代理类是创建了的 , 比如例子中的刘小爱
  • 动态:代理类是不用创建的
在Java里有一个类叫Proxy , 翻译过来就是代理的意思 。
用这个类可以动态构建一个代理类对象:
使用newProxyInstance()方法 , 该方法是一个静态方法 , 所以用类名直接可以调用 。
将该方法拆分记忆:new 创建;Proxy 代理;Instance 实例化;也就是创建代理对象 , 很好记 。
现在我们来仔细分析该方法的三个参数 , 看源码:
①ClassLoader loader
ClassLoader , 类加载器 , 昨天就接触过 。
我们写的类 , 本质上是.java文件 , 同时开发工具会自动编译成.class文件 , 但它们都是存放在硬盘上的 。
而类加载器就是将类加载进内存 , 这样才能够运行 。
②Class<?>[
interfaces
interfaces , 接口的意思 。 我个人学Java的一个习惯是先理解这个英文单词是什么意思再去记忆其作用 。
并且很多命名规则都是见名知意的 。
这个参数就是接口对应的Class对象 , 什么接口?就是被代理类实现的接口 , 因为它可以实现很多个接口 , 所以是一个数组 。
③InvocationHandler h
InvocationHandle , 翻译过来就是调用处理器 。
它是一个接口 , 我们继续看它的源码:
该接口只有一个方法invoke:
  • proxy:这个就是代理对象
  • method:这个也就是代理对象调用的方法(例子中的sing方法、dance方法、sleep方法)
  • args:这个是方法中的参数
好 , 以上就是对newProxyInstance()方法的说明 , 完全弄懂了这个方法 , 也就弄懂了动态代理 。
我们现在将代码补全:
①被代理类的类加载器
被代理类是谁?例子中就是LuoTianYi , 首先要获取它对应的Class对象 。
ty.getClass():三种获取Class对象之一 , ly是LuoTianYi的对象 , 利用对象ly的getClass方法 。
拿到其对应的Class对象后 , 可以调用getClassLoader()方法获取对应的类加载器 。
Java里面的很多方法看名字就能知道它的作用是什么 。
所以ty.getClass().getClassLoader()就是获取被代理类LuoTianYi的类加载器.
②被代理类所实现的接口
同样的道理 , 见名知意:
ty.getClass().getInterface()就是获取被代理类实现的接口对应的Class对象 , 例子中就是star这个接口 。
③调用处理器
这是一个接口 , 所以使用匿名内部类创建其实现类对象 , 同时重写接口中的invoke方法 。
这块代码的编写 , 其实也就是例子中刘小爱这个类对star接口中的三个抽象方法的重写 。
这是具体的业务逻辑 , 根据不同的需求编写不同的代码 , 其它的代码都是基本不变的 。