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

简介: 图文详解 Spring AOP,看完必懂。。

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

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


AOP产生背景

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


什么是AOP

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

  • 找到横切点:首要目标确定在程序的哪个位置进行横切逻辑
  • 横切逻辑(业务代码):横切逻辑代码,这个就是横切业务代码,与aop无关
  • 织入:将横切逻辑织入到横切点


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


既然是横向的编程,那么在我们的程序中,哪些可以作为横线切入点呢?


看下示例代码:

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
        }
    }
}

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

image.png

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

  • 使用构造函数创建对象
  • 构造函数执行
  • 对象方法调用
  • 对象方法执行
  • 静态方法调用
  • 静态方法执行
  • 反射读写对象字段


目标1:找到横切点

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


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


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

  • 如果横切点作用于对象(对象字段、对象方法、构造函数),则不仅需要返回AccessibleObject,还需要返回当前对象,因为调用通过反射调用对象方法需要传入当前对象。
  • 如果横切点作用于类,则仅返回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联盟没有定义,只有方法级别的)。


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

image.png

比如在MethodInvocation,就是返回Method。


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

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

在aop联盟的接口定义:

image.png

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


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

Object invoke(MethodInvocation invocation) throws Throwable;


目标3:织入

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

  • 静态织入:采用自定义类加载器机制。自定义类加载器根据织入规则在加载class文件期间对class文件动手织入横切逻辑,然后将改动后的class文件交给JVM运行。
  • 动态织入:由多种选择,动态代理(JDK Proxy)、动态字节码生成技术(cglib)


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


来一个完整的流程图:

image.png

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


AOP联盟的接口很少:

image.png

相关文章
|
5月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
617 0
|
9月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1370 13
|
4月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
6月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
620 6
|
6月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
916 25
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
514 24
|
11月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
1505 0

热门文章

最新文章