代理设计模式与 AOP
本文为大家讲解代理模式,包括静态代理的作用和代码实现、动态代理的作用、使用反射实现动态代理的过程,从而理解 AOP 的原理。
代理模式分为:静态代理和动态代理。代理模式实现的功能和我们生活中的代理一样,类似于中介公司。也就是代理对象帮助被代理对象完成功能,被代理对象可以在代理对象已有的功能基础上,扩展代理对象的功能。
比如在已存在的多个具有相同接口的目标类的各个方法上增加一些系统功能,经常会使用到代理模式,例如:方法执行前后的日志打印,计算方法的运行时间、异常处理、事务等等。
一、静态代理
静态代理的介绍与代码实现
下面我们通过一个例子来认识静态代理的作用,假设我们有一个操作数据库的 Dao 服务接口 DaoService ,里面包括查询方法 query() 和更新方法 update(),程序中需要操作数据库的有订单服务 OrderService 类,它实现了 DaoService 接口。
我们思考一个问题,如果需要在查询方法 query() 和更新方法 update() 执行的前后需要加入日志打印功能,也就是说在方法执行前打印一行日志,表示方法开始执行,在方法执行后打印一行日志,表示方法执行完毕。
大家可以思考,以上的问题我们可以怎么解决?
任何人都能想到的最直接的办法就是,在每个实现了 DaoService 接口的类的 query() 方法和 update() 方法的前后加上两行日志就可以了。这种方法其实产生了很多的重复代码,不是一个好的解决办法。如果实现了 DaoService 接口的类有很多,那么我们就会在这些类的 query() 方法和 update() 方法加很多日志代码。
另外一个解决办法就是用静态代理来实现,用一个代理类 DaoServiceProxy 实现 DaoService 接口,让它来对实现了 DaoService 接口的类进行代理,在代理类的query() 方法和 update() 方法的前后加上两行日志就可以了。这样做的好处是不管有多少 DaoService 的实现类,只需要加一个代理类,在代理类的具体方法上加两行日志就可以了,重复代码得到了极大的减少。
示例代码如下:
// DaoService接口
interface DaoService {
void query();
void update();
}
// 被代理类OrderService
class OrderService implements DaoService {
@Override
public void query() {
System.out.println("OrderService.query()");
}
@Override
public void update() {
System.out.println("OrderService.update()");
}
}
// 代理类
class DaoServiceProxy implements DaoService {
DaoService dao;
// 创建代理类对象的时候,实际上传入一个被代理类的对象
public DaoServiceProxy(DaoService dao) {
this.dao = dao;
}
@Override
public void query() {
System.out.println("query()开始执行!");
dao.query();
System.out.println("query()执行完毕!");
}
@Override
public void update() {
System.out.println("update()开始执行!");
dao.update();
System.out.pri