图文详解 Spring AOP,看完必懂!

点击关注公众号,Java干货及时送达d83f4e128f62bf322b91a340c3383838.png

64a672e027017adfaa10b5d17a842518.png 国内最强微服务框架,没有之一!

826cafcdf2d409a966d5e0349f1e2805.png 几乎覆盖 Spring Boot 所有操作!

9f9a9a7bc8bb811287cc3ec1490dcc84.png 2023 全新 Java 面试题(2500+)


来源:blog.csdn.net/duxd185120/article/details/109210224

学习一个模块的设计主要是看接口设计,通过接口设计我们就能够从整体知道模块怎么实现的,具体实现就是组装这些接口来进行实现的,知道了模块接口设计,实现也就变得很简单了。

本文主要从aop背景出发点,来自己去想需要哪些接口,就能够描述一个模块的功能设计规则。

AOP产生背景

使用面向对象编程 ( OOP )有一些弊端,当需要为多个不具有继承关系的对象引人同一个公共行为时,例如日志、安全检测等,我们只有在每个对象里引用公共行为,这样程序中就产生了大量的重复代码,程序就不便于维护了。

所以就有了一个对面向对象编程的补充,即面向方面编程 ( AOP ), AOP 所关注的方向是横向的,区别于 OOP 的纵向。

什么是AOP

什么是面向方面编程,3个过程:

开发者主要关心的是横切逻辑的编写,只需要很少的代码编写确定横切点有哪些,而不需要去为每个横切点添加横切逻辑,不然就是面向对象编程了。

既然是横向的编程,那么在我们的程序中,哪些可以作为横线切入点呢?另外,如果你近期准备面试跳槽,建议在Java面试库小程序在线刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。

看下示例代码:

public class Test {
    public static void main(String[] args) {
        //@1
       B b = new B();
       //@2
       b.method();

       //@3
        B.say();
    }

    static class B {
        //字段
        //@4
        private String name;
        //构造方法
        public B() {
            //@1.1
            }
        //对象方法
        public void method(){
            //@2.2
        }
        //静态方法
        static void say(){
            //@3.3
        }
    }
}

所以我们可以将横切点主要分为两大类:字段、方法。方法又分为很多种,

dffd354066ffa5aa64ad2bd98a61217a.png

横切点有很多地方,从代码上看得见的,有如下几个地方:

目标1:找到横切点

那么怎么去定义一个横切点呢?怎么用一个接口来描述一个横切点呢?

在Java中,一切皆对象,在Java中一个类有2方面内容:字段、方法(构造函数、对象方法、静态方法),java中使用AccessibleObject来抽象公共行为。方法:就是一段可以执行的程序,一段代码。

所以在横切点接口中,首先一个功能就是返回给用户当前横切点,有两种情况:

另一个接口功能就是要不要考虑在横切点来控制多个横切逻辑的调用。这个可以有框架支持,也可以由横切点控制。这对应的就是责任链模式的API设计。比如tomcat中的Filter链式调用就是以集合形式调用;netty中的Handler组织就是以链表形式。如果是以集合形式调用,则在横切点接口需要定义一个方法来链式调用。(aop联盟的JoinPoint采用是集合形式调用)

那么AOP联盟使用JointPoint接口来定义横切点。

public interface Joinpoint {

 Object proceed() throws Throwable;

 Object getThis();

 AccessibleObject getStaticPart();

}

Object proceed() throws Throwable: 链式调用横切点

Object getThis(); 返回连接点当前对象。如果当前连接点是静态,比如静态方法,则该方法返回null,因为反射不需要对象,而且静态方法是通过类调用的,压根就没有对象,所以返回null。spring aop不支持静态方法的拦截,所以在spring中这里返回的就是目标对象(被代理对象)

AccessibleObject getStaticPart(); 返回连接点静态部分,对于连接点是方法,返回的就是Method对象。

现在对连接点的设计比较清晰了,然后就是对连接点的扩展了,比如可执行程序(构造方法、Method)的子接口,字段的子接口(aop联盟没有定义,只有方法级别的)。

资源分享:Spring Boot 学习笔记

AOP联盟对连接点接口的设计:

3c25324f78ba43a61b8fb9d0dd50ee05.png

比如在MethodInvocation,就是返回Method。

目标2:横切逻辑(增强)抽象定义

增强的抽象,其实就需要连接点信息,毕竟增强是要投入到一个地方的,所以需要连接点信息。

在aop联盟的接口定义:

551144a6d848b9482452e2b80ae3d80e.png

Advice作为一个tag标识,在aop联盟中使用拦截器来作为增强的命名,这里完全可以去掉Interceptor,而直接定义一个MethodAdvice。之所以定义为Interceptor,是因为拦截器命名更符合编程命名规范,让人从命名就知道接口功能。

在MethodInterceptor,传入连接点信息(因为是方法拦截,所以这里是方法级别的连接点接口定义)

Object invoke(MethodInvocation invocation) throws Throwable;

目标3:织入

首先就是怎么织入。织入由两种方案。

  • 静态织入:采用自定义类加载器机制。自定义类加载器根据织入规则在加载class文件期间对class文件动手织入横切逻辑,然后将改动后的class文件交给JVM运行。

  • 动态织入:由多种选择,动态代理(JDK Proxy)、动态字节码生成技术(cglib)

spring采用动态织入。动态织入就是生成代理对象,代理对象中维护了当前连接点所有拦截器,然后调用目标方法时被代理类拦截,在代理类中作aop功能。

最新 Spring 面试题整理好了,点击Java面试库小程序在线刷题。

来一个完整的流程图:

f3b534fe95974d03da79e94ef9566342.png

Spring AOP的实现基于AOP联盟接口标准设计实现的,全局看下aopalliance有哪些接口以及接口的API设计,我们上面已经分析完了。

AOP联盟的接口很少:

17372b9aa7d177ea7062f95f8bcc91c4.png


课程推荐

如果你想系统学习 Spring Boot,推荐下我的《Spring Boot 核心技术课》,基于最新 3.x 版本,几乎覆盖 Spring Boot 所有核心知识点,一次付费,永久学习…

感兴趣的扫码联系订阅学习:

d24f5cf41d359ba551407f33e10f2178.png

加栈长微信报名学习

4db827de46a8a59e60206d9751918797.jpeg

快速通过请备注:399

猜你喜欢

转载自blog.csdn.net/youanyyou/article/details/132372654
今日推荐