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 模式,示例类图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p720RMb9-1594796589022)(G:\workspace\csdn\learn-document\spring-framework\相关书籍\image-20200714080904449.png)]
示例代码:

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版)》- 计文柯
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值