0.源码地址
https://gitee.com/heaboy-boy/aop
这套代码写得非常漂亮,省略了所有无关代理的细节,比较好理解。本文基于这套代码解释反射和代理。建议阅读前在本地把项目跑通。
1.反射和代理概述
反射是实现代理的手段之一。代理可以对方法增强。
什么是“对方法增强”呢?如果一个方法执前行后,需要进行某些操作,在这个方法之外添加“某些操作”,就是对方法增强。
去学校图书馆“读书”前要刷卡,进入图书馆,“读书”完毕,离开图书馆并签离。其中,“读书”就是目标方法(等着被增强的方法),不管读什么书,都要“刷卡”“进入”“离开”“签离”,这些都是方法的增强。
为了体现代理的必要性,举一个更实际的例子。
用户小明登录进入某网站后台。在后台页面,小明每次向服务器提交请求,服务器server都会想,这是小明登陆后发送的请求吗?如果server认为这是已登录用户小明的请求,他就会满足小明的要求,去数据库查些数据,返回给小明。server用于接收小明请求的的方法(例如修改信息、删除信息)可能多达几十个,在每个方法前面都加几行认证小明的代码,显然代码耦合度太高。这时,我们就可以通过代理,把“认证身份”环节作为其它方法(修改信息、删除信息)的增强,只写一遍,从而解耦。
实际上,代理除了帮助上述情况解耦,还可以实现其它功能,但未在第0节的源码中体现。为了防止对阅读造成障碍,不在本文一一列举。
2.静态代理
2.1 基本流程
a.新建接口。接口将会被目标类和代理类实现,接口内声明的方法就是要增强的方法。
b.创建一个目标类,实现刚刚新建的接口,类中方法是我们要增强的目标。
c.创建代理类,实现和目标类相同的接口。
d.创建启动类或main方法,模拟对代理的调用
2.2 特点
a.实现和目标类(要代理的目标)同样的接口
b.在代理类方法体中创建目标类对象,调用对象的方法。由于实现了相同接口,代理类方法名和目标类方法名总能一一对应。
c.可以围绕目标类对象的实例执行任何操作。
2.3 实现细节
第2节静态代理对应第0节提供源码的包com.heaboy.aopdemo.staticproxy。流程a、b、c、d分别对应案例项目中的四个类TargetInterface、Target
、TargetProxy、TargetUser。
假设你已有一定的java基础,下面仅对TargetProxy代理类解释。
代理类即实现静态代理的关键类,下面是代理类的一个方法
public void method1() {
System.out.println("执行方法前...");
new Target().method1();
System.out.println("执行方法后...");
}
一目了然,方法体的第一行表示,调用目标方法前执行某些操作。第二行表示新建目标类的实例,调用目标类方法method1,第三行表示执行完毕目标类的方法后要执行的某些操作。