前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring学习笔记 | AOP 面向切面编程

Spring学习笔记 | AOP 面向切面编程

作者头像
windealli
发布2024-05-11 17:10:04
1690
发布2024-05-11 17:10:04
举报
文章被收录于专栏:windealliwindealli

什么是AOP

AOP,全称是面向切面编程(Aspect-Oriented Programming)。

AOP是一种编程范式,其主要目标是提高模块化程度,以提高代码的可重用性和可维护性。

为什么需要AOP

在传统的面向对象编程(OOP)中,我们通常会将代码按照功能进行模块化。然而,有些功能(例如日志记录、事务管理、安全性检查等)可能会跨越多个模块,这些功能我们通常称之为"横切关注点"。在OOP中处理这些横切关注点通常会导致代码的重复和分散,这就是所谓的"代码污染"。

AOP的主要思想就是将这些横切关注点从业务逻辑代码中分离出来,单独进行模块化,然后在运行时将它们动态地"织入"到需要的业务逻辑中。这样,我们就可以将关注点的代码集中管理,提高代码的可重用性和可维护性。

Spring AOP 的底层实现原理

Spring AOP使用了代理模式,通过在运行时创建代理对象来实现切面的织入。这样,当调用一个被代理的方法时,Spring AOP就可以在方法调用前后插入切面代码,实现例如日志记录、事务管理等功能。

AOP的核心概念

  1. 横切关注点-Crosscutting Concerns 横切关注点是指软件系统中跨越多个模块的功能和关注点。例如日志记录、安全检测、权限控制等。
  2. 切面-Aspect 切面是AOP的基本构建块,它是对横切关注点的模块化表示。切面可以包含一些通知(Advice)和切入点(Pointcut)。切面是将横切关注点封装起来的模块。
  3. 连接点-JoinPoint 连接点是在应用程序中你想要插入切面的点。在Spring AOP中,连接点总是表示一个方法的执行。
  4. 通知-Advice 通知是切面模块的具体实现,它定义了切面需要完成的工作。Spring AOP支持五种类型的通知
    • 前置通知(Before)
    • 后置通知(After)
    • 返回后通知(After Returning)
    • 抛出异常后通知(After Throwing)
    • 环绕通知(Around)。
  5. 切入点-PointCut 切入点是一组连接点的集合,它定义了通知应该在哪些连接点上执行。 Spring AOP使用AspectJ的切入点表达式语言来定义切入点。
  6. 目标对象-Target Object 目标对象是被一个或者多个切面所通知的对象。也就是包含连接点的对象。
  7. 代理-Proxy 代理是一个被AOP框架动态创建的对象,它用来实现切面代码的插入。 在Spring AOP中,代理有两种
    • JDK动态代理
    • CGLIB代理。
  8. 织入-Weaving 织入是将切面插入到目标对象以创建新的代理对象的过程。织入可以在编译时(使用AspectJ编译器),类加载时,或者运行时(如Spring AOP)进行。

如何使用AOP

好的,让我们以日志记录为例,来看一下如何使用Spring AOP进行面向切面编程。

识别横切关注点:在这个例子中,我们的横切关注点是日志记录,因为我们希望在每个方法执行前后都记录日志。

定义切面:我们可以创建一个新的Java类,并使用@Aspect注解来定义这个类为一个切面:

代码语言:javascript
复制
@Aspect
@Component
public class LoggingAspect {
    // ...
}

定义通知:在切面类中,我们可以定义一些通知方法。例如,我们可以定义一个前置通知和一个后置通知,分别在方法执行前后记录日志

代码语言:javascript
复制
@Aspect
@Component
public class LoggingAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        logger.info("开始执行方法:{}", joinPoint.getSignature().getName());
    }

    @After("execution(* com.example.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        logger.info("方法执行结束:{}", joinPoint.getSignature().getName());
    }
}

定义切入点:在这个例子中,我们的切入点是com.example.service包下的所有方法。我们使用execution表达式来定义这个切入点,并在@Before@After注解中直接使用。如果你希望在多个通知中复用同一个切入点,你可以使用@Pointcut注解来定义一个切入点:

代码语言:javascript
复制
@Aspect
@Component
public class LoggingAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        logger.info("开始执行方法:{}", joinPoint.getSignature().getName());
    }

    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        logger.info("方法执行结束:{}", joinPoint.getSignature().getName());
    }
}

配置AOP:最后,我们需要在Spring的配置中启用AOP。如果你使用的是Spring Boot,那么AOP已经默认启用了。如果你使用的是传统的Spring,你可以在你的配置类中添加@EnableAspectJAutoProxy注解来启用AOP:

代码语言:javascript
复制
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // ...
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 海天二路搬砖工 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是AOP
  • 为什么需要AOP
  • Spring AOP 的底层实现原理
  • AOP的核心概念
  • 如何使用AOP
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档