Spring系统学习-什么是AOP?为啥使用AOP?

问题思考

我们为啥要使用AOP?

来看一个案例:

声明计算器接口Calculator,包含加减乘除的抽象方法

java 复制代码
public interface Calculator {
    int add(int i, int j);
    int sub(int i, int j);
    int mul(int i, int j);
    int div(int i, int j);
}
java 复制代码
public class CalculatorPureImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        System.out.println("方法内部 result = " + result);
        return result;
    }
    @Override
    public int sub(int i, int j) {
        int result = i - j;
        System.out.println("方法内部 result = " + result);
        return result;
    }
    @Override
    public int mul(int i, int j) {
        int result = i * j;
        System.out.println("方法内部 result = " + result);
        return result;
    }
    @Override
    public int div(int i, int j) {
        int result = i / j;
        System.out.println("方法内部 result = " + result);
        return result;
    }
}

创建带日志功能的实现类

java 复制代码
public class CalculatorLogImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        System.out.println("[日志] add 方法开始了,参数是:" + i + "," + j);
        int result = i + j;
        System.out.println("方法内部 result = " + result);
        System.out.println("[日志] add 方法结束了,结果是:" + result);
        return result;
    }
    @Override
    public int sub(int i, int j) {
        System.out.println("[日志] sub 方法开始了,参数是:" + i + "," + j);
        int result = i - j;
        System.out.println("方法内部 result = " + result);
        System.out.println("[日志] sub 方法结束了,结果是:" + result);
        return result;
    }
    @Override
    public int mul(int i, int j) {
        System.out.println("[日志] mul 方法开始了,参数是:" + i + "," + j);
        int result = i * j;
        System.out.println("方法内部 result = " + result);
        System.out.println("[日志] mul 方法结束了,结果是:" + result);
        return result;
    }
    @Override
    public int div(int i, int j) {
        System.out.println("[日志] div 方法开始了,参数是:" + i + "," + j);
        int result = i / j;
        System.out.println("方法内部 result = " + result);
        System.out.println("[日志] div 方法结束了,结果是:" + result);
        return result;
    }
}

这个时候我们发现代码缺陷:

  • 对核心业务功能有干扰,导致程序员在开发核心业务功能时分散了精力
  • 附加功能分散在各个业务功能方法中,不利于统一维护

解决这两个问题,核心就是:解耦。我们需要把附加功能从业务功能代码中抽取出来。

解决问题的困难:要抽取的代码在方法内部,靠以前把子类中的重复代码抽取到父类的方式没法解决。所以需要引入新的技术。

这其实就是我们的AOP思想 - 解耦

AOP概述

Spring AOP(Aspect-Oriented Programming)是Spring框架提供的一种面向切面编程的支持。它允许开发者通过定义切面(Aspect)来将横切关注点(Cross-cutting Concerns)与核心业务逻辑分离,从而提高代码的可维护性和可重用性。

在Spring AOP中,切面是一个模块化的单元,它横跨多个类和对象,用于封装横切关注点。横切关注点是那些在应用程序中散布在各处的功能,如日志记录、事务管理、安全性等,它们与核心业务逻辑无关,但又需要在多个地方重复使用。

Spring AOP通过使用代理模式和动态代理技术,在运行时动态地将切面织入到目标对象的方法中,从而实现横切关注点的功能。开发者可以使用注解或XML配置来定义切面和切点,以及指定切面的行为和执行时机。

Spring AOP的核心概念包括:

  • Aspect(切面):封装了横切关注点的模块。一个切面是由多个join points和相关的advice组成。

  • Join Point(连接点):在程序执行过程中的某个点,如方法调用或异常抛出,可以被AOP织入的地方。

  • Advice(通知):在特定的join point执行的代码,如before、after、around等类型的通知。

  • Pointcut(切入点):一个或多个join points的集合,通过表达式语言来定义哪些join points会被编织上advice。

  • Weaving(织入):将aspect和advice插入到程序的join points的过程,Spring AOP在运行时通过代理实现这一点。

  • Target Object(目标对象):被通知的对象,即被AOP增强的真实对象。

  • Proxy(代理):包含目标对象以及附加的AOP行为的对象。

Spring AOP主要通过两种代理机制实现AOP:

  • JDK动态代理:用于实现接口的代理,利用Java反射机制创建代理对象。

  • CGLIB(Code Generation Library):用于实现类的代理,通过字节码生成库来创建子类对象。

通过使用Spring AOP,开发者可以更容易地维护和扩展应用,因为那些与业务逻辑无关的代码可以被集中管理和修改,而不必改动核心的业务逻辑代码。这有助于降低系统复杂度,提高代码的可读性和可维护性。

为啥Spring 要使用AOP?

Spring框架选择使用AOP(Aspect Oriented Programming,面向切面编程)的主要原因在于解决传统面向对象编程(OOP)中遇到的一些挑战,特别是在处理横切关注点(cross-cutting concerns)方面。下面列出了一些关键的原因:

  • 解耦合:在OOP中,横切关注点(如日志记录、缓存、权限检查、事务管理等)常常需要在多个地方重复编码,这导致代码耦合度高,难以维护和扩展。AOP允许将这些关注点从核心业务逻辑中分离出来,降低系统的耦合度。

  • 代码重用和模块化:通过AOP,你可以编写一次横切关注点的代码,并在多个不同的地方使用它,无需在每个受影响的模块中重复相同的代码。这提高了代码的重用性和模块化。

  • 简化开发和维护:AOP使得开发人员可以专注于业务逻辑的实现,而将通用的服务(如日志、事务管理)留给AOP切面处理。这不仅简化了开发流程,也便于后期维护,因为所有的日志或事务相关代码都集中在一个地方。

  • 透明性:使用AOP,可以向现有代码添加新的功能,而无需修改原有代码。例如,如果需要在所有数据库操作前后添加日志记录,可以通过AOP轻松实现,而不需要修改每个涉及数据库操作的方法。

  • 灵活的配置:Spring AOP允许通过XML配置文件或者注解来定义切点(pointcuts)、通知(advice)和切面(aspects),这提供了非常灵活的配置选项,使得开发者可以根据需要轻松调整AOP的行为。

  • 事务管理:Spring AOP特别擅长处理事务管理。通过声明式事务管理,开发者只需在配置文件或注解中指定事务边界,而不需要在代码中显式地管理事务的开始和结束。

  • 性能优势:虽然AOP引入了额外的运行时开销,但由于它减少了代码的重复和耦合,总体上可以带来更好的性能,尤其是在大型企业级应用中。

相关推荐
jinanwuhuaguo28 分钟前
(第三十三篇)五月的文明奠基:OpenClaw 2026.5.2版本的文明级解读
android·java·开发语言·人工智能·github·拓扑学·openclaw
MegaDataFlowers29 分钟前
英语六级我还在背单词:Unit 1(Lesson 2)
学习
东京老树根1 小时前
SAP学习笔记 - BTP SAP Build12 - SAP Build Content Package
笔记·学习
xmjd msup1 小时前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
952361 小时前
SpringBoot统一功能处理
java·spring boot·后端
Lyyaoo.1 小时前
优惠券秒杀业务分析
java·开发语言
消失的旧时光-19431 小时前
统一并发模型:线程、Reactor、协程本质是一件事(从线程到协程 · 第6篇·终章)
java·python·算法
勿忘初心12212 小时前
Java 国密 SM4 加密工具类实战(Hutool + BouncyCastle)|企业级数据加密 + 兼容 JDK8
java·数据安全·数据加密·后端开发·企业级开发·国密 sm4
庞轩px2 小时前
第8篇:原子类与CAS底层原理——无锁并发的实现
java·cas·乐观锁·aba·无锁编程·自旋
rleS IONS2 小时前
SpringBoot中自定义Starter
java·spring boot·后端