AOP面向切面编程

目录

一、AOP概念 

1. 切面

 2. 通知

3. 切入点

4. 连接点

5. 织入

 二、注解及表达式相关

1. @Aspect 声明切面类 

2. @Pointcut 声明切入点

3. execution 表达式

4. within 表达式

5. within() 和 execution() 的区别 

6. args 表达式

7. bean 表达式

三、利用AOP实现指定IP段限制上传附

一、AOP概念 

面向切面编程(Aspect-Oriented Programming,AOP)是一种编程范式,旨在提高代码的模块化和封装性。在AOP中,程序被分解成核心业务逻辑和横切关注点(cross-cutting concerns)。这些横切关注点是那些在各个模块中被广泛使用的代码,比如日志、安全性、事务管理等。

AOP通过将这些横切关注点从核心业务逻辑中分离出来,实现了模块化的开发方式。AOP的主要概念是切面(Aspect),切面是一种横切关注点的模块化实现方式,可以在不同模块中重复使用,提高了代码的重用性和可维护性。

总的来说,面向切面编程是一种提高代码模块化和封装性的编程范式,通过将横切关注点从核心业务逻辑中分离出来,实现了更加灵活和可维护的代码结构。一般来说,AOP切面编程都是非业务代码,比如打印日志。否则,业务不一样,就很难抽离出来变成公共的

1. 切面

切面是横切关注点的模块化实现。它可以包含多个“通知”(Advice)和“切入点”(Pointcut),定义了在哪里以及如何实现横切逻辑。

假设有四个方法,需要在每个方法中都输出一个日志,传统发放就需要在每个方法中写一条输出语句,如果有一万个方法,就需要将该输出语句写一万次,那这种方法显然是不可行的。所以需要将这条打印语句抽离封装好,需要用的的方法调用封装好的打印语句就好了。

 上图所示,将长的椭圆形看成一个个方法,然后在方法上横切一刀,每个椭圆形就会有个横切面,这个横切面就是我们需要抽取出来的业务。我们把全部的横切面都集成一个大的横切面,就类似于将公共模块封装,需要用的时候直接调用即可。也就是说,把上面的四个横切面整合成一个切面对象,这就是面向切面编程。

不使用AOP, 就需要在每个方法中都添加一个打印语句

public class UserService {
    
    public void addUser(User user) {
        // 日志输出
        System.out.println("正在处理...");
        // 核心业务逻辑
    }

  public void delUser(Integer id) {
        // 日志输出
        System.out.println("正在处理...");
        // 核心业务逻辑
    }

  public void updateUser(User user) {
        // 日志输出
        System.out.println("正在处理...");
        // 核心业务逻辑
    }

  public void queryAllUser() {
        // 日志输出
        System.out.println("正在处理...");
        // 核心业务逻辑
    }
}

 使用AOP

添加AOP依赖

  <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1. 将日志输出的代码抽取出来

public class UserService {
    
    public void addUser(User user) {
        // 核心业务逻辑
    }

  public void delUser(Integer id) {
        // 核心业务逻辑
    }

  public void updateUser(User user) {
        // 核心业务逻辑
    }

  public void queryAllUser() {
        // 核心业务逻辑
    }
}

2. 定义一个切面类(logAspect)

@Aspect  // 定义一个切面类
@Component  // 标记该类为 spring 容器的 Bean,把这个切面类交给容器管理
@Order(Ordered.LOWEST_PRECEDENCE -1)  // 定义加载 spring 容器中 Bean 加载顺序的,值越小优先级越高
public class LoggingAspect {

     
    // 定义一个切入点,匹配 UserService 的所有方法
    //  @Pointcut 注解用于指定哪些方法需要被拦截并执行增强处理(例如,日志记录、权限检查等)
    //  @execution() 方法用于匹配哪些方法需要增强
    // 第一个 * 表示 匹配任何返回值
    // 第二个 * 表示 匹配所有方法
    // .. 表示 匹配任何参数,无论有无参数都匹配
    @Pointcut("execution(* com.example.UserService.*(..))")
    public void userServiceMethods() { }

    
    // 前置通知:在方法执行前记录日志
    @Before("userServiceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("正在处理...");
    }

}

 在这个例子里,LoggingAspect 就是一个切面,它的前置通知在 UserService 的方法执行前自动插入日志记录逻辑。这样,你的业务代码就干净了,不再需要手动写日志逻辑。 

 2. 通知

通知定义了切面的具体行为,也就是在何时、何地、以何种方式对目标方法进行增强。根据增强发生的时机,通知分为五种:前置通知、后置通知、返回通知、异常通知、环绕通知。

前置通知Before Advice):在方法调用前执行。
后置通知After Advice):在方法调用后执行。
返回通知After Returning Advice):在方法成功返回后执行。
异常通知After Throwing Advice):在方法抛出异常后执行。
环绕通知Around Advice):在方法执行的前后都执行,可以完全控制方法的执行过程。

3. 切入点

切入点(Pointcut)是用来定义你想要拦截哪些方法,即哪些方法会被增强。配合"通知" 一起工作,通知决定了在方法执行前、执行后或抛出异常时执行什么逻辑,即拦截后要做什么事情

4. 连接点

连接点可以理解为业务逻辑层中的方法。程序执行当中的一个方法调用、一个异常抛出都可以作为连接点。 

5. 织入

 织入是将切面与目标对象(业务代码)结合的过程。在 Spring AOP 中,织入通常发生在运行时&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值