而AOP是Spring框架中的重要组成部分。
代理模式
- 介绍:代理对象可以在客户和目标之间起到中介作用,去掉客户端不能看到的内容和服务增添客户需要的额外服务;
- GOF概括:为其他对象提供一种代理以控制对这个对象的访问。
代理类
关于自定义代理模式我就不赘述了,直接从java.lang.reflect包下的代理模式开始讲,Java自带的代理模式叫Proxy,这个类只有四个公开的方法,最重要的方法是newProxyInstance(),下面是这四个方法,蛮看一下:
- getInvocationHandler(Object proxy):返回指定代理实例的调用处理程序。
- getProxyClass():返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。
- isProxyClass():当且仅当指定的类通过 getProxyClass 方法或
newProxyInstance 方法动态生成为代理类时,返回 true。 - static Object newProxyInstance():返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
处理器
Proxy中有很多方法和InvocationHandler相关,说来也很奇怪,虽然Proxy直译是代理,但是它并不真的处理,而是交给了InvocationHandler,InvocationHandler直译是处理器,或者叫调用处理程序,它是一个接口,内部只有一个 invoke() 方法,invoke()才是真正负责代理的方法。
源码:
处理器
既然说了处理器才是真正的代理者,就先从它开始看,invoke有3个参数:
- 第一个是Proxy本身,使用的话容易会出现死循环,只要关心后面两个即可;
- 第二个参数是Method,Method显然是反射用的;
- 而args是数组,而Method的invoke()方法的第二个参数也是数组,直接使用args即可;Method的invoke()方法的第一个参数是Object,指明我们调用的是哪一个类的Method。
我们可以在invoke()之前或者之后做一些处理,这一部分逻辑就由我们自己设计,这一部分的设计也就是我们用代理模式的目的所在。
public class ProxyHandler implements InvocationHandler {
private Object proxied;
public ProxyHandler(Object proxied) {
this.proxied = proxied;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO 在执行add()之前的处理
// 转调具体目标对象的方法
return method.invoke(proxied, args);
// TODO 在执行add()之后的处理
}
}
抽象主题
public interface AbsBiz {
public void add();
}
真正主题
public class UserBiz implements AbsBiz {
public void add() {
System.out.println("insert into tableName...");
}
}
测试类
这里呢,只要注意一下Proxy的newProxyInstance的三个参数就好了:
- 第一个参数是ClassLoader,直接通过Class获得即可;
- 第二个参数是Class,也可以直接通过Class获得即可,但是要明确这个Class指的是接口的Class;
- 第三个参数是InvocationHandler,也就是前面提到的处理器。
public class Test {
public static void main(String args[]) {
UserBiz biz = new UserBiz();
AbsBiz proxySubject = (AbsBiz) Proxy.newProxyInstance(biz.getClass().getClassLoader(),
biz.getClass().getInterfaces(), new ProxyHandler(biz));
proxySubject.add();
}
}
补充:
自定义代理模式的三个角色:抽象主题(Subject),实际主题(RealSubject)、代理(Proxy),其中实际主题和代理都继承自抽象主题,而SDK下,将Proxy这一部分提了出来,实用性更广。
AOP代理除了JDK的,还有CGlib代理,有兴趣的可以自己看一下。