当前课程知识点:JAVA程序设计进阶 > 第八章 反射与代理机制 > 8.3 Java动态代理 > Video
那下面这一节的话
我们给大家介绍一下
Java的动态代理
大家看到这个名字顾名思义
动态代理是相对于静态代理而言的
那动态代理肯定是要去改进
我们静态代理当中的它的缺点了
我们先看一下
要实现JAVA的动态代理
都需要用到哪些类
我们最关键要用到是Proxy这个类
Proxy这个类它属于
我们java.lang.reflect这个包
那它是Java动态代理机制的主类
提供了一组静态方法
来为我们一组接口
动态地生成代理类以及相应的对象
那这个类里面有好几个重要的方法
我给大家逐一介绍一下
第一个方法就是
static InvocationHandler
getlnvocationHandler
然后Object proxy
那这个方法实际上它是用于获取
指定代理对象所关联的调用处理器
调用处理器就是
InvocationHandler
就是当你想获得
某一代理对象的调用处理器的时候
你通过这个getlnvocationHandler
这个方法就可以获得
这个方法是个静态方法
然后它的返回值
就是InvocationHandler
我们再看一下第二个方法
第二个方法
叫static Class getProxyClass
然后参数是
第一个参数是ClassLoader
类装载器loader
然后第二个参数是一对接口
那这个方法是用于获取
关联与指定类装载器
和一组接口的动态代理类的类对象
它实际上它返回值是Class
是个类型 然后它是个静态的方法
那我们看一下第三个方法
static boolean isProxyClass
然后Class cl
那这个方法是用来判断
我们指定的类对象
它是否是一个动态的代理类
也就是说在我们这个
static boolean isProxyClass
参数里面给出了一个Class cl
那实际上它是想判断说
这个cl它是不是一个动态代理类
如果是的话就返回true
如果不是返回false
那这个static boolean isProxyClass
这个方法它本身
也是一个static方法
我们再看一下第四个方法
static Object newproxyInstance
ClassLoader loader
然后Class数组 后面interfaces
然后紧接着后面又跟着一个
InvocationHandler h
那这个方法它的作用
是为指定的类装载器
也就是我们第一个参数
ClassLoader loader
以及一组接口
所以一组接口就是我们第二个参数
Class(数组)interfaces
以及调用处理器
也就是我们第三个这个参数
InvocationHandler h
来去生成一个动态代理类的实例
简而言之就是说你要用这个方法
来去生成一个动态代理类的实例
那这个实例所表示说是
我是有关乎哪个类加载器的
然后是关乎于哪些接口的
然后是关乎哪个调用处理器的
我们先看一下
我们的这个调用处理器的这个接口
它这是属于我们这个包
java.lang.reflect
InvocationHandler
它是个interfaces
然后它里面定了invoke方法
用来去集中处理
在动态代理类对象上的方法调用
那通常在该方法
实现对委托类的这个代理访问
我们看一下这个语句
Object invoke
Object proxy
Method method Object args
大家看一下这个方法是invoke
然后invoke它要执行的
是哪个代理呢
那就在Proxy里面指定
然后这是第一个参数
那第二个参数就有关说你这个
你要调用哪些方法
那实际是在第二个参数
Method method里面指定
那第三个参数就是说
就是说你要调用这个方法的时候
这个方法的输入的参数是什么呢
所以大家可以看到
这个invoke这个方法很有意思
就是说你可以去任意的
去调一个代理对象它的哪个方法
只需要把这些方法参数传进去
就可以执行它
我们来看一个例子吧
首先我们定义了一个
这个抽象的这个一个角色
一个接口 interfoce Subject
然后这里面定义了一个方法
pubic void request
然后我们看一下它的真实角色
Class RealSubject
implements Subject
实现了接口Subject
那这里面首先定义了
它的一个构造方法
public RealSubject
然后紧接着定义了它的
实现了它的request方法
public void request
然后打印出来说From real Subject
好了我们这个real Subject
这个类就定义完了
我们再看一下怎么去调用
就站在客户端的角度怎么去调用它
import java.lang.reflect.Method
把Method这个方法从包
java.lang.reflect.Method中
导入进来
然后import java.lang.reflect.
InvocationHandler
InvocationHandler是个接口
我们接着再往下看
Class DynamicSubject
implements InvocationHandler
就是我们定义这个类
实现了InvocationHandler这个接口
private Object sub
定义了一个私有的对象sub
然后pubic Dynami subject
这是它的构造方法无参数的构造方法
紧接着第二个构造方法
pubic Dynami subject
然后参数是Object obj
然后它是做的工作
就是把obj赋值给我们成员变量sub
所以就是sub等于obj
好 我们再往下看
public Object invoke
Object proxy Method method
Object args throws Throwable
大家看这个属于invoke方法了
invoke方法就是要调用
我们所代理的对象的它的一些方法
我们往下看
System.out.println
bcalling+method
它就是说我打印出来说
在我调用哪个方法之前
紧接着就是
method.invoke sub args
就用这个method这个方法
然后再调用invoke
其实method是个对象
method这个对象调用invoke方法
然后它的两个参数
一个是sub 一个是args
这样就执行我们这个方法了
然后紧接着我们打印出来
after calling+method
然后最后return null
所以大家看到就是
我们整个这个invoke就是方法
就是pubic Object invoke方法
就能够实现对于我们代理对象的
某个方法的执行
那紧接着我们看一下怎么去调用它
我们import java.lang.reflect.
InvocationHandler
然后import Proxy
import Constructor
import Method等等
这四个类或者接口
那我们紧接着定义
public class Client定义这个类
然后类里边我们看看主方法
public void main
String args throws Throwable
然后这主方法里干什么事情呢
RealSubject rs
=new RealSubject
我们这实例化出一个
真正的一个对象
这个只是这里用来被指定代理类
然后紧接着invocationHandler ds
=new DynamicSubject rs
实际上大家注意这句话就很有
语句就很有意思
我们看等号右边
new Dynamic Subject rs
实际上是说
我的生成一个动态的代理
那我这个动态代理
我所代表的是哪个真实对象呢
是代表的rs这个真实对象
那所以我这个动态的代理
它的这个调用的处理器
invocationHandler
就用ds来进行表示 进行表示了
那再往下Class cls=rs.get Class
这是我们得到这个代理
它的这个类型
然后Subject subject
=Subject Proxy.newProxyInstance
cls.getClassLoader
cls.getInterfaces ds
然后大家看到这句话里面
就是我们这个生成了
一个Subject对象
实际上Subject对象
实际上它是通过Proxy这个代理
它的newProxyInstance方法
来去产生的
然后给定的参数
第一个是它的类装载器
第二个是它的相应的接口
第三个是它的这个调用处理器
最后我们才是去调用
它的request方法
也就是Subject.request
大家看看这个运行结果吧
就刚才我们这几页PPT
合起来的运行结果是这样的
before calling public abstract
void Subject.request
也就是说我在调用了这个
Subject request方法之前
紧接着我们调用它了
调用它的话
它是From real subject
也从我们真实的这个对象里面
把它的这个request给调用了
结果输出了 然后紧接着
after calling public abstract
void Subject.request
调完了以后我又做了一些继续处理
大家看其实这个例子
实际上是我们告诉大家
说你可以给一个真实的对象
你给它生成一个动态代理
那生成这个动态代理的话
既然是个代理
你可以在这个真实对象的方法
执行之前先做一些预处理
执行之后你还可以做一些后处理
所以你就可以增加一些
你想干的这个事情
而通过这个动态代理的话
它的好处就是能够让你
更加方便的去实现这些代理的过程
那我们总结一下
它动态代理都有哪些特点
我们从这几个方面进行分析
首先从包就是public
从包的角度来分析一下
如果我们要代理的这个接口
都是public
那么它就会被定义在是在顶层包
也就是说上面没有其它包了
就是在最上面 最顶层了
但是如果我们要代理的这个接口
interfaces中有非public接口
那它就将被定义在该接口所在的包
比如说这个我们这个代理了
这个com.ibm包中的
某个非public接口A
那么新生成的代理类所在的包
就是com.imb
那这样设计的目的
是为了最大程度的保证
动态代理类不会因为包管理的问题
而无法被成功定义并且访问
好 这个是动态代理包的
第一个特点
那第二个特点
我们从类修饰符方面进行分析
那这样的一个代理类
具有final和public修饰符
那意味着它可以被所有的类访问
但是它不能够被继承
因为这个类本身
具有final和public
那我们再从类名去分析一下
动态代理的这个特点
我们产生了动态代理
它最后的这格式
是一个$ProxyN
那其实N的话
是一个逐一递增的阿拉伯数字
代表是说我Proxy类
第N次生成的动态代理类
但是需要注意的是说
并不是我们每次调用
Proxy的静态方法
来创建动态代理类的时候
都会使得这个N值递增
那原因是说当我们对同一组接口
就是说包括
接口排列的顺序相同的话
我们试图重新创建
动态代理类的时候
它还是会比较聪明来判断说
我先前是不是已经创建好
这个相应的代理类的类对象了
如果有的话就不会再新创建
这样的话就好处是可以节省
不必要的这个代码重复
提高带代理类的一个创建效率
我们再从这个类继承关系
来去看一下我们动态代理类
大家看下面这张图
因为这个Proxy左上角是一个类
那底下的话是$ProxyN
是我们一个具体的
这么一个这个Proxy类
这个类的话它继承于
我们上面Proxy 左上角Proxy类
那它同时可能也会实现了
其它的一些接口
实现了比如说接口A 接口B
其它的接口
所以这些是我们动态代理的一个特点
那优点和缺点呢 我们先说优点吧
动态代理类和静态代理相比
最大的好处是
接口中声明的所有方法
都被转移到调用处理器
一个集中的方法进行处理
就是都集中到
invocationHandler.invoke这个方法
这样的话就在接口数量比较多的时候
我们可以进行灵活处理
而不需要像静态代理那样
每一个方法都要进行中转
这就比较高效
虽然在我们刚才那例子当中
没有看出来
因为invoke方法它在它方法体内
嵌入了一个具体的外围业务
那我们在实际当中
比如说我们可以类似到
大家用javaEye的时候
有个javaEE架构
那spring架构
AOP有这样的配置外围业务的话
那我们可以类似这样的方法
来去处理都是比较好的
那动态代理有哪些缺点
我们虽然说它已经设计的非常好了
那就是说它小小的遗憾就是
它始终无法摆脱
仅仅支持interface代理的弱点
虽然说实际上它已经做的很好了
它目前仅能只是支持interface
但我相信我们很多情况下用接口
用interface
来定义很多公共的特性
这已经是足够使用了
那关于JAVA的动态代理的内容
我们就介绍到这里
-1.0 导学
--Video
-1.1 线程的基本概念
--Video
-1.1 线程的基本概念--作业
-1.2 通过Thread类创建线程
--Video
-1.2 通过Thread类创建线程--作业
-1.3 线程的休眠
--Video
-1.3 线程的休眠--作业
-1.4 Thread类详解
--Video
-1.5 通过Runnable接口创建线程
--Video
-1.5 通过Runnable接口创建线程--作业
-1.6 线程内部的数据共享
--Video
-2.0 导学
--Video
-2.1 线程同步的思路
--Video
-2.2 线程同步的实现方式—Synchronization
--Video
-2.3 线程的等待与唤醒
--Video
-2.4 后台进程
--Video
-2.5 线程的生命周期与死锁
--Video
-2.6 线程的调度
--Video
-3.0 导学
--Video
-3.1 线程安全与线程兼容与对立
--Video
-3.2 线程的安全实现-互斥同步
--Video
-3.3 线程的安全实现-非阻塞同步
--Video
-3.4 线程的安全实现-无同步方案
--Video
-3.5 锁优化
--Video
-4.0 导学
--Video
-4.1 URL对象
--Video
-4.2 URLConnection对象
--Video
-4.3 Get请求与Post请求
--Video
-4.4 Socket通信原理
--Video
-4.5 Socket通信实现
--Video
-5.0 导学
--Video
-5.1 Socket 多客户端通信实现
--Video
-5.2 数据报通信
--Video
-5.3 使用数据报进行广播通信
--Video
-5.4 网络聊天程序
--Video
-6.0 导学
--Video
-6.1 Java虚拟机概念
--Video
-6.2 Java虚拟机内存划分
--Video
-6.3 Java虚拟机类加载机制
--Video
-6.4 判断对象是否存活算法及对象引用
--Video
-6.5 分代垃圾回收
--Video
-6.6 典型的垃圾收集算法
--Video
-6.7典型的垃圾收集器
--Video
-7.0 导学
--Video
-7.1 集合框架与ArrayList
--Video
-7.2 LinkedList
--Video
-7.3 HashMap与HashTable
--Video
-7.4 TreeMap与LinkedHashMap
--Video
-7.5 HashSet
--Video
-8.0 导学
--Video
-8.1 Java反射机制
--Video
-8.2 Java静态代理
--Video
-8.3 Java动态代理
--Video
-8.4 Java 反射扩展-jvm加载类原理
--Video
-8.5 Java进阶课程总结
--Video