欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 Spring AOP 的设计与实现

程序员文章站 2022-05-04 08:54:59
Spring AOP 的设计与实现文章目录Spring AOP 的设计与实现前言项目环境1.JVM 的动态代理特性1.1 静态代理1.2 动态代理2.Spring AOP 的设计分析3.Spring AOP 的应用场景4.参考前言上一篇《Spring AOP 基础概述》,我们了解了 Spring AOP 的一些基础概念,比如 Advice,Pointcut,Advisor;本章将会讨论以下几个议题JVM 的动态代理特性Spring AOP 的设计分析Spring AOP 的应用场景项目环境...

Spring AOP 的设计与实现

前言

上一篇《Spring AOP 基础概述》,我们了解了 Spring AOP 的一些基础概念,比如 Advice,Pointcut,Advisor;本章将会讨论以下几个议题

  • JVM 的动态代理特性
  • Spring AOP 的设计分析
  • Spring AOP 的应用场景

相关文章

项目环境

1.JVM 的动态代理特性

在 Spring AOP 实现中,使用的核心技术是动态代理。通过 JDK 动态代理技术可以为任意 Java 对象创建代理对象,对于具体使用来说,这个特性是通过 Java Reflection API (反射)来完成。

1.1 静态代理

在了解 Java Reflection 之前,我们先通过一个简单的示例复习一下 Proxy 模式,示例类图如下:
荐
                                                        Spring AOP 的设计与实现
示例代码:

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