JavaEE中的MVC(四)AOP代理

时间:2021-03-14 09:12:56

而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代理,有兴趣的可以自己看一下。