动态代理与AOP(1)
代理的作用与概念 动态代理与AOP
1. 代理的作用与概念
1). 代理类使用的背景
有一个已经开发好的类,但是现在要为其增加异常处理、日志、统计方法的运行时间、事务处理等功能,但是开发好的类不能修改或者没有办法修改,该如何做?
2). 代理类和目标类
(1). 目标类
已经开发好且不能被修改的类称为目标类
(2). 代理类和目标类的关系
[1]. 代理类的功能与目标类的功能一样
[2]. 只是在执行目标类相关功能的前或者后增加了新的辅助功能。
{1}. 代理类的每个方法名与目标类的每个方法名都一样
{2}. 代理类的每个方法都要调用目标类的每个方法
{3}. 代理类的每个方法在调用目标类的每个方法的前或者后都会加上系统的额外功能
[3]. 客户端不直接使用目标类,而是直接使用代理类,代理类实际上是在调用目标类的功能。
3). 代理类出现前后对比
(1). 代理类出现之前,客户端直接调用目标类的功能
(2). 代理类出现之后
[1]. 客户端不直接调用目标类的功能,而是直接调用与目标类相对应的代理类的功能
[2]. 为了保证代理类和目标类具有相同的功能,代理类和目标类必须实现相同的接口
2. 面向方面编程(AOP)
1). AOP诞生的背景 -----交叉业务的出现
举例:有三种业务如下
处理学生、课程和管理的三种业务,有各自的C、R、U、D。但是无论这些类的各自的业务如何不同,都会涉及到安全、事务管理和日志三个方面的内容。、
交叉业务:就是不同模块具有的共同的业务。如图
2). 面向切面编程的基本概念
(1). 用代码描述交叉业务
(2). AOP的基本知识
[1]. 交叉业务不能独立抽象出来的原因
由于某个具体的交叉业务仅仅模块功能的一部分,而不是一个整体,所以这些交叉业务不可以抽象成独立的类,也就不能实例化成具体的对象。
[2]. 面向切面编程:对交叉业务编程的问题就称为AOP(Aspect Oriented Programming)
(3). AOP与代理的关系
[1]. AOP与代理联系的纽带
思想:将和切面有关的代码移动到原始方法的周围,这和直接在方法中编写切面代码之后的整体运行效果是一致的。
【AOP与代理的关联】 如果将切面的代码移到原始方法的周围,原始方法看做目标类的方法,那么移动以后的切面代码+原始代码就是代理类对应的方法
[2]. 可以采用代理的方式来实现AOP
【结论】代理是实现AOP的核心和关键技术。只要是AOP,就一定会涉及代理技术。
(4). 代理技术的分类
按照是否是在程序运行期间产生代理类可以将代理分为静态代理和动态代理
[1]. 静态代理:就是手动为每一个目标类的每一个方法都增加交叉业务,也就是手动为每一个目标类增加代理类
【缺点】如果目标类数量非常多或者目标类中的功能非常多,直接使用静态代理的方式来为目标类增加交叉业务会非常的繁琐。
[2]. 动态代理:通过特定的设置,在程序运行期间指示JVM动态地生成类的字节码。这种动态生成的类往往被用作代理类,即动态代理类。
【也就是运行时做编译的事情并且把生成的字节码加载成这个类的Class对象】
3. 动态代理类
1). 实现动态代理类的分类
这个分类依据的是JVM是否可以从目标类是否实现了某些特定的接口来获取目标类的各个功能。这个依据可以指示JVM根据目标类中有哪些功能在对应的代理类中实现
(1). 通过JVM生成动态代理类
[1]. 前提:要求目标类必须实现某些接口
[2]. JVM生成的动态代理类只能作用于具有相同接口目标类的代理类
【局限】要求目标类实现特定的接口才能生成和目标类对应的动态代理类
(2). 通过第三方类库CGLIB生成动态代理类
[1]. 适用的情况:目标类没有实现相应的接口,又需要为这个类动态生成代理类。此时第三方类库CGLIB是最好的选择。
[2]. CGLIB可以为目标类动态生成目标类的子类,并把这个动态生成的子类作为这个类的代理类。
2). 代理类为目标代码添加交叉业务(切面)的位置
代理类的各个方法通常要调用目标类相应的方法,并将目标类对应方法的返回结果作为自身的返回值提供给外界。这个时候,代理类可以在以下位置为对应目标类中对应的方法增加指定的交叉业务代码:
(1). 在调用目标类的目标方法之前
(2). 在调用目标类的目标方法之后
(3). 在调用目标类的目标方法之前和之后
(4). 在调用目标类的目标方法异常的catch块中