当前课程知识点:JAVA程序设计进阶 >  第八章 反射与代理机制 >  8.3 Java动态代理 >  Video

返回《JAVA程序设计进阶》慕课在线视频课程列表

Video在线视频

Video

下一节:Video

返回《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的动态代理的内容

我们就介绍到这里

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

第六章 Java虚拟机

-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

第七章 深入集合Collection

-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

Video笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。