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引入了额外的运行时开销,但由于它减少了代码的重复和耦合,总体上可以带来更好的性能,尤其是在大型企业级应用中。

相关推荐
我真的是大笨蛋3 小时前
K8S-Pod(下)
java·笔记·云原生·容器·kubernetes
碳水加碳水3 小时前
Java代码审计实战:XML外部实体注入(XXE)深度解析
java·安全·web安全·代码审计
努力也学不会java4 小时前
【设计模式】 原型模式
java·设计模式·原型模式
方渐鸿5 小时前
【2024】k8s集群 图文详细 部署安装使用(两万字)
java·运维·容器·kubernetes·k8s·运维开发·持续部署
学亮编程手记5 小时前
K8S v1.33 版本主要新特性介绍
java·容器·kubernetes
Haven-6 小时前
Java-面试八股文-JVM篇
java·jvm·面试
我真的是大笨蛋6 小时前
JVM调优总结
java·jvm·数据库·redis·缓存·性能优化·系统架构
wjs0406 小时前
Git常用的命令
java·git·gitlab
superlls6 小时前
(算法 哈希表)【LeetCode 349】两个数组的交集 思路笔记自留
java·数据结构·算法
田里的水稻7 小时前
C++_队列编码实例,从末端添加对象,同时把头部的对象剔除掉,中的队列长度为设置长度NUM_OBJ
java·c++·算法