首页 > 编程语言 >转:什么是AOP编程思想

转:什么是AOP编程思想

时间:2023-05-26 13:35:03浏览次数:43  
标签:思想 Spring 编程 AspectJ 切面 AOP 日志 public

转自:https://www.duidaima.com/Group/Topic/ArchitecturedDesign/12108

AOP 的核心思想是将横切关注点抽象为一个独立的模块(称之为“切面”),然后在需要应用它的地方进行调用。比如,在需要记录日志的方法中,我们可以定义一个切面来负责日志记录,这样所有调用该方法的地方都会被自动添加上日志功能,而不必修改原有方法。AOP 通过使用诸如“切点”、“连接点”、“通知”等概念,使得开发人员可以灵活地控制切面的应用范围和时机。

AOP 的常用实现方式是利用代理对象来实现切面功能。在 Java 领域中,常见的 AOP 框架有 Spring AOP 和 AspectJ 等。除了 Java,AOP 的思想还可以应用于其它编程语言和平台。

Spring AOP 和 AspectJ AOP

Spring AOP 和 AspectJ AOP 是两种不同的 AOP 实现。Spring AOP 基于动态代理实现,是 Spring 框架中的 AOP 实现,主要用于解决 Spring 容器中 Bean 的横切关注点问题。由于使用了动态代理,所以只支持方法级别的切面(即只能织入方法的执行)。尽管 Spring AOP 的性能略逊于 AspectJ,但对于大部分应用来说,性能影响不大。

相比之下,AspectJ AOP 是一个独立的、功能更强大的 AOP 实现。它不仅支持方法级别的切面,还支持字段、构造器等其他切面,并可通过编译时织入或加载时织入的方式实现 AOP。这使得 AspectJ 比 Spring AOP 更加灵活和强大。同时,Spring 可以与 AspectJ 结合使用,以提供更强大的 AOP 功能。

实现 AOP 的方式

  • 动态代理:通过代理模式,为目标对象生成一个代理对象,然后在代理对象中实现横切关注点的织入。动态代理可以分为JDK动态代理(基于接口)和 CGLIB 动态代理(基于类)。
  • 编译时织入:在编译阶段,通过修改字节码实现 AOP。AspectJ 的编译时织入就是这种方式。
  • 类加载时织入:在类加载阶段,通过修改字节码实现 AOP。AspectJ 的加载时织入就是这种方式。

AOP的实现方式取决于具体需求和技术选型。对于 Spring 应用来说,通常可以使用 Spring AOP 满足大部分需求,如果需要更强大的 AOP 功能,可以考虑使用 AspectJ。

AOP 的相关概念

image

实战1

使用spring的AOP,实现日志切面,打印每次方法的入参和返回。
首先,我们需要在Spring配置文件中启用AOP:

<beans>
    <aop:aspectj-autoproxy />
    <!-- 其他配置 -->
</beans>

然后,我们可以创建一个切面类来实现日志记录:

@Aspect
@Component
public class LoggingAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAspect.class);
    @Pointcut("execution(* com.example.*.*(..))")
    public void logMethod() {}
    @Before("logMethod()")
    public void logMethodEntry(JoinPoint joinPoint) {
        LOGGER.info("Entering method: {} with arguments: {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
    }
    @AfterReturning(pointcut = "logMethod()", returning = "result")
    public void logMethodExit(JoinPoint joinPoint, Object result) {
        LOGGER.info("Exiting method: {} with result: {}", joinPoint.getSignature().getName(), result);
    }
}

在上面的代码中,我们定义了一个切点 logMethod(),它匹配所有 com.example 包下的方法。然后,我们使用 @Before 和 @AfterReturning 注解来分别记录方法的入参和返回值。在 JoinPoint 对象中,我们可以获取方法的签名和参数。

最后,我们可以在需要记录日志的方法上添加 @LogMethod 注解来启用日志切面:

@Service
public class MyService {
    @LogMethod
    public void doSomething(String arg1, int arg2) {
        // 方法实现
    }
}

这样,每次调用 doSomething 方法时,日志切面都会记录方法的入参和返回值。对于 Spring Boot 项目,实现日志切面的方法与普通的 Spring 项目类似。只需要在 Spring Boot 的配置类上添加 @EnableAspectJAutoProxy 注解即可启用 AOP。

下面是一个示例:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // 其他配置
}

然后,我们可以创建一个切面类来实现日志记录:

@Aspect
@Component
public class LoggingAspect {
    // 堆代码 duidaima.com
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAspect.class);
    @Pointcut("execution(* com.example.*.*(..))")
    public void logMethod() {}
    @Before("logMethod()")
    public void logMethodEntry(JoinPoint joinPoint) {
        LOGGER.info("Entering method: {} with arguments: {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
    }
    @AfterReturning(pointcut = "logMethod()", returning = "result")
    public void logMethodExit(JoinPoint joinPoint, Object result) {
        LOGGER.info("Exiting method: {} with result: {}", joinPoint.getSignature().getName(), result);
    }
}

在上面的代码中,我们定义了一个切点 logMethod(),它匹配所有 com.example 包下的方法。然后,我们使用 @Before 和 @AfterReturning 注解来分别记录方法的入参和返回值。在 JoinPoint 对象中,我们可以获取方法的签名和参数。

最后,我们可以在需要记录日志的方法上添加 @LogMethod 注解用日志:

@Service
public class MyService {
    @LogMethod
    public void doSomething(String arg1, int arg2) {
        // 方法实现
    }
}

这样,每次调用 doSomething 方法时,日志切面都会记录方法的入参和返回值。

实战2

使用AspectJ AOP,实现日志切面,打印每次方法的入参和返回。使用 AspectJ AOP 结合 Spring Boot 也是非常简单的。下面是一个示例:
首先,我们需要在 pom.xml 文件中添加 AspectJ 相关的依赖:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.6</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.6</version>
</dependency>

然后,我们可以创建一个切面类来实现日志记录:

@Aspect
@Component
public class LoggingAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAspect.class);
    @Pointcut("execution(* com.example.*.*(..))")
    public void logMethod() {}
    @Before("logMethod()")
    public void logMethodEntry(JoinPoint joinPoint) {
        LOGGER.info("Entering method: {} with arguments: {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
    }
    @(pointcut = "logMethod()", returning = "result")
    public void logMethodExit(JoinPoint joinPoint, Object result) {
        LOGGER.info("Exiting method: {} with result: {}", joinPoint.getSignature().getName(), result);
    }
}

在上面的代码中,我们定义了一个切点 logMethod(),它匹配所有 com.example 包下的方法。然后,我们使用 @Before 和 @AfterReturning 注解来分别记录方法的入参和返回值。在 JoinPoint 对象中,我们可以获取方法的签名和参数。

最后,我们需要在 Spring Boot 的配置类上添加 @EnableAspectJAutoProxy 注解来启用 AspectJ AOP:

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // 其他配置
}

这样,我们就可以在需要记录日志的方法上添加 @LogMethod 注解用日志:

@Service
public class MyService {
    @LogMethod
    public void doSomething(String arg1, int arg2) {
        // 方法实现
    }
}

这样,每次调用 doSomething 方法时,日志切面都会记录方法的入参和返回值。

总结

好的,下面是 AOP 的总结:
AOP(Aspect-Oriented Programming)是一种编程范式,它通过将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,以模块化的方式实现这些关注点。AOP 的核心思想是将程序的功能分解成不同的关注点,然后通过切面将这些关注点模块化,从而提高代码的可维护性和可重用性。

AOP 的主要概念包括:

  • 切面(Aspect):横切关注点的模块化,它包括切点和通知。
  • 切点(Pointcut):程序中需要被拦截的方法或者类。
  • 通知(Advice):在切点处执行的代码,包括前置通知、后置通知、异常通知、最终通知和环绕通知。
  • 连接点(Join Point):程序中可以被拦截的点,通常是方法调用或者异常处理等。
  • 织入(Weaving):将切面应用到目标对象并创建新的代理对象的过程。

AOP 的实现方式包括:

  • 静态代理:手动编写代理类,将切面代码硬编码到代理类中。
  • 动态代理:使用 JDK 动态代理或者 CGLIB 动态代理生成代理对象,将切面代码动态织入到代理对象中。
  • AspectJ:一种基于 Java 语言的 AOP 框架,它提供了更加灵活和强大的 AOP 功能,支持编译时织入和运行时织入两种方式。

AOP 的优点包括:

  • 提高代码的可维护性和可重用性,将横切关注点从业务逻辑中分离出来,使得代码更加模块化。
  • 降低代码的耦合度,将不同的关注点分离开来,使得代码更加灵活和可扩展。
  • 提高代码的可读性和可理解性,将关注点的代码集中在一起,使得代码更加清晰和易于理解。

AOP 的缺点包括:

  • 增加了代码的复杂度,需要额外的学习和理解成本。
  • 可能会影响程序的性能,特别是在运行时织入切面时,会增加额外的开销。
  • 可能会导致调试和排错变得更加困难,特别是在切面代码中存在错误时,可能会影响整个程序的运行

标签:思想,Spring,编程,AspectJ,切面,AOP,日志,public
From: https://www.cnblogs.com/Ceri/p/17434464.html

相关文章

  • QT编程: 编写低功耗BLE蓝牙调试助手(Android系统APP)
    由于工作需要,需要利用QT平台完成手机与ble蓝牙的通讯,所以就找了各种资料,算是初步的能够连接完成demo代码,但是依旧有些代码没有理解,比如特性那一片的代码,稍后还得研究啊(对了,这是低功耗蓝牙,不是经典蓝牙,看清楚了,当初不清楚经典蓝牙和低功耗蓝牙,浪费我一个星期,说多了都是泪,下面是代码......
  • Angular Material教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介AngularMaterial是AngularJS开发人员的UI组件库。AngularMaterial的可重用UI组件有助于构建有吸引力,一致且功能强大的Web页面和Web应用程序,同时遵循现代Web设计原则,如浏览器可移植性,设备独立性和优雅降级。AngularMaterial入门教程-从简单的步骤了解角度材料,从基......
  • Rust async 编程
    Rustasync编程AsynchronousProgramminginRust:https://rust-lang.github.io/async-book/中文书名《Rust异步编程指南》:https://github.com/rustlang-cn/async-bookRust语言圣经(RustCourse):https://course.rs/advance/async/getting-started.html一、GettingStarted1.......
  • 【java】同步异步和多线程编程
    Java基本概念并发基于时间段内的,同时发生(处理多个任务的能力,时间段)存在同步和互斥的问题(任务之间的时序问题)同步:前一个处理的结果作为下一个处理的资源(互相之间有依赖)互斥:不能同时使用临界资源。解决时序问题的机制:锁,信号量,原子操作Java中的多线程机制并行(完全......
  • 异步编程(Thread、ThreadPool、Task、异步关键字async/await)
    一、什么是异步Thread,是微软.Net1.0推出;ThreadPool 是微软.Net2.0推出;Task是微软.Net4.0推出;async/await是微软.Net5.0推出;       同步和异步主要用于修饰方法。当一个方法被调用时,调用者需要等待该方法执行完毕并返回才能继续执行,我们称这个方法是同步方法;当一个方......
  • UNIX网络编程:socket & select() 实现clients/server通信
    一、问题引入UNIX网络编程卷1:套接字联网API(第三版)第6章介绍了I/O复用可以通过select()的单进程服务器与多客户端通信。UNIX下可用的5中I/O模型:阻塞式I/O非阻塞式I/OI/O(select和poll)信号驱动式I/O(SIGIO)异步I/O(POSIX的aio_系列函数)其中前面4种可以分为同步I/O,第五种为......
  • PB编程,API函数和PB编程绝招
    1. 如何使PB窗口总在最上层 通过SetWindowPos函数吧窗口的显示层次修改为HWND_TOPMOST,就可以使指定窗口永远不会被其他窗口覆盖,该函数声明为: Function Long SetWindowPos(Long hwnd, Long  ord, Long x, Long y, Long dx, Long dy, Long uflag) Library ......
  • 通过Java技术学习C++编程
    C++是一种广泛应用于系统级编程和高性能计算领域的强大编程语言。尽管Java和C++是两种不同的语言,但是通过Java技术的学习和应用,我们可以更好地理解C++的概念和编程技巧。本文将以Java为基础,展示一些C++代码示例,帮助读者掌握C++的基本语法和常用功能。HelloWorld程序让我们从经典......
  • Java编程核心之继承
    学习目标掌握继承的优点和实现掌握子类重写父类方法掌握继承下构造方法的过程掌握抽象类和抽象方法的使用前言:在写程序的过程中会有一些重复的代码,我们可以使用继承的方式把重复的代码提取到父类中,这样在子类中,就可以起到优化代码的作用。继承的定义继承是面向对象语法的三大特征之......
  • C语言编程—函数的介绍
    函数是一组一起执行一个任务的语句。每个C程序都至少有一个函数,即主函数main(),所有简单的程序都可以定义其他额外的函数。您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的,但在逻辑上,划分通常是根据每个函数执行一个特定的任务来进行的。函数声明告......