荐 Spring AOP 的设计与实现
Spring AOP 的设计与实现
文章目录
前言
上一篇《Spring AOP 基础概述》,我们了解了 Spring AOP 的一些基础概念,比如 Advice,Pointcut,Advisor;本章将会讨论以下几个议题
- JVM 的动态代理特性
- Spring AOP 的设计分析
- Spring AOP 的应用场景
相关文章
- Spring AOP 基础概述
- Spring AOP 的设计与实现
- Spring AOP 创建 AopProxy 代理对象原理分析
- Spring AOP 拦截器调用的实现(整理中…)
项目环境
- Java 8
- Spring framework 5.2.2.RELEASE
- github 地址:https://github.com/huajiexiewenfeng/spring-aop-demos
- 本章模块:proxy
1.JVM 的动态代理特性
在 Spring AOP 实现中,使用的核心技术是动态代理。通过 JDK 动态代理技术可以为任意 Java 对象创建代理对象,对于具体使用来说,这个特性是通过 Java Reflection API (反射)来完成。
1.1 静态代理
在了解 Java Reflection 之前,我们先通过一个简单的示例复习一下 Proxy 模式,示例类图如下:
示例代码:
Subject 接口
public interface Subject {
void request();
}
Subject 接口的具体实现 RealSubject
public class RealSubject implements Subject {
public void request() {
System.out.println("request 方法执行");
}
}
代理类 Proxy
public class Proxy {
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
public void request() {
preOperation();
subject.request();
postOperation();
}
private void postOperation() {
System.out.println("后置处理...");
}
private void preOperation() {
System.out.println("前置处理...");
}
}
Client 调用类
public class Client {
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject());
proxy.request();
}
}
执行结果:
前置处理...
request 方法执行
后置处理...
在 Proxy 的调用过程中,如果客户(Client)调用 Proxy 的 request 方法,会在调用目标对象的 request 方法的前后调用一些增强方法,而这一系列的操作对目标对象来说是隐形的,目标对象毫不知情,这就是 Proxy 模式。
1.2 动态代理
JDK 中已经实现了这个 Proxy 模式,在基于 Java 虚拟机设计应用程序时,只需要直接使用这个特性就可以了。相关实现类位置:
- java.lang.reflect.Proxy
这个对象生成之后,所起的作用就类似于 Proxy 模式中的 Proxy 对象。在使用时,还需要为代理对象(Proxy)设计一个回调方法,这个回调方法起到的作用是,在其方法的前后执行一系列增强动作。比如上面例子中的 preOperation() 和 postOperation 方法。这个回调方法,如果在 JDK 中实现,需要实现 java.lang.reflect.InvocationHandler 接口
代码如下:
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
在这个接口方法中,只声明了一个 invoke 方法,参数含义如下:
- 第一个参数是代理对象
- 第二个参数是 Method 方法对象,表当前 Proxy 被调用的方法
- 第三个参数是被调用方法的参数
通过以上这些信息,在 invoke 方法实现中,已经可以了解 Proxy 的部分用意了。至于怎样让 invoke 方法和 Proxy 挂钩,只要在调用 Proxy.newIntance 方法生成具体的 Proxy 对象时,把 InvocationHandler 设置到参数里面就可以了,剩下的由 Java 虚拟机来完成。
示例代码:
public class DynamicProxyDemo {
public static void main(String[] args) {
Subject subject = new RealSubject();
Subject proxyInstance = (Subject) java.lang.reflect.Proxy.newProxyInstance(
subject.getClass().getClassLoader(),
new Class<?>[]{Subject.class},
new InvocationHandlerImpl(subject));
proxyInstance.request();
}
static class InvocationHandlerImpl implements InvocationHandler {
private Object target;
public InvocationHandlerImpl(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object reuslt = null;
postOperation();
reuslt = method.invoke(target, args);
preOperation();
return reuslt;
}
private void postOperation() {
System.out.println("后置处理...");
}
private void preOperation() {
System.out.println("前置处理...");
}
}
}
执行结果:
后置处理...
request 方法执行
前置处理...
可以看到通过 JDK 动态代理也实现了静态代理示例同样的效果。
2.Spring AOP 的设计分析
AOP 模块是 Spring 的核心模块,虽然在 Java 社区里 AspectJ 是最完整的 AOP 框架,但是 Spring AOP 也提供了另一种实现,这种实现并不是 AspectJ 的竞争者,相反,Spring AOP 将 AspectJ 集成进来,为 IoC 容器和 Spring 应用开发提供了一个一致性的 AOP 解决方案。
Spring AOP 的核心技术是 JDK 动态代理技术,以动态代理技术为基础,设计出了一系列 AOP 的实现。比如前置通知,后置通知,异常通知等等。同时,Spring AOP 还提供了一系列的 Pointcut 来匹配切入点,可以使用现有的切入点来设计横切面,也可以扩展相关的 Pointcut 方法来实现切入需求。
在 Spring AOP 中,虽然对于 AOP 的使用者来说,只需要配置相关 Bean 的定义即可,但是 Spring AOP 为了能让 AOP 起作用,需要完成一系列的过程,比如:
- 需要为目标对象建立代理对象,这个代理对象可以通过使用 JDK 的 Proxy 来完成,也可以通过 CGLIB 来完成。
- 需要启动代理对象的拦截器功能来拦截各个切面。
这些设计是通过一系列的 Adapter 来实现的,通过这些 Adapter 可以把 AOP 切面和 Proxy 模式有机的结合起来,具体细节后续文章继续讨论,本篇只是简单介绍。
3.Spring AOP 的应用场景
Spring AOP 为 IoC 的使用提供了更多的便利,一方面,应用可以直接使用 AOP 的功能,设计应用和切面关注点,把多个模块的功能抽象出来,并通过简单的 AOP 使用,灵活地切入到模块中,比如可以通过 AOP 实现应用程序的日志功能,Web 接口的权限验证等等。另一方面,在 Spring 内部,一些支持模块也是通过 Spring AOP 来实现的,比如事务处理。
4.参考
- 《Spring技术内幕:深入解析Spring架构与设计原理(第2版)》- 计文柯
本文地址:https://blog.csdn.net/xiewenfeng520/article/details/107360972
上一篇: React实现新闻网站--使用动态路由获取不同列表内容
下一篇: Static、继承、抽象类