首页 > 编程语言 >AOP 编程

AOP 编程

时间:2024-01-20 16:23:59浏览次数:35  
标签:连接点 Spring 编程 代理 切面 通知 AOP

AOP 编程

目录

1. AOP和OOP

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程

在说到AOP前,很容易想到OOP(面向对象编程),这两个都是编程思想中十分重要的部分,不同点在于:

  • OOP面向对象编程:纵向切割,针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分;
  • AOP面向切面编程:横向切割,针对业务处理过程中的切面进行提取,它所面对的是处理过程的某个步骤或阶段,以获得逻辑过程的中各部分之间低耦合的隔离效果。
  • AOP 采取横向抽取机制,补充了传统纵向继承体系(OOP)无法解决的重复性,代码优化(性能监视、事务管理、安全检查、缓存),将业务逻辑和系统处理的代码(关闭连接、事务管理、操作日志记录)解耦。

img

2. AOP中的一些概念

术语

  • 切面(Aspect): Aspect 声明类似于 Java 中的类声明,事务管理是AOP一个最典型的应用。在AOP中,切面一般使用 @Aspect 注解来使用,在XML 中,可以使用 <aop:aspect> 来定义一个切面。
  • 连接点(Join Point): 一个在程序执行期间的某一个操作,就像是执行一个方法或者处理一个异常。在Spring AOP中,一个连接点就代表了一个方法的执行。
  • 通知(Advice):在切面中(类)的某个连接点(方法出)采取的动作,会有四种不同的通知方式: around(环绕通知),before(前置通知),after(后置通知), exception(异常通知),return(返回通知)。许多AOP框架(包括Spring)将建议把通知作为为拦截器,并在连接点周围维护一系列拦截器。
  • 切入点(Pointcut):表示一组连接点,通知与切入点表达式有关,并在切入点匹配的任何连接点处运行(例如执行具有特定名称的方法)。由切入点表达式匹配的连接点的概念是AOP的核心,Spring默认使用AspectJ切入点表达式语言。
  • 介绍(Introduction): introduction可以为原有的对象增加新的属性和方法。例如,你可以使用introduction使bean实现IsModified接口,以简化缓存。
  • 目标对象(Target Object): 由一个或者多个切面代理的对象。也被称为"切面对象"。由于Spring AOP是使用运行时代理实现的,因此该对象始终是代理对象。
  • AOP代理(AOP proxy): 由AOP框架创建的对象,在Spring框架中,AOP代理对象有两种:JDK动态代理和CGLIB代理
  • 织入(Weaving): 是指把增强应用到目标对象来创建新的代理对象的过程,它(例如 AspectJ 编译器)可以在编译时期,加载时期或者运行时期完成。与其他纯Java AOP框架一样,Spring AOP在运行时进行织入。

通知类型

  • 前置通知(Before advice):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
  • 后置通知(After returning advice):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
  • 异常通知(After throwing advice):在方法抛出异常退出时执行的通知。
  • 最终通知(After (finally) advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
  • 环绕通知(Around Advice):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。

环绕通知是最常用的通知类型。和AspectJ一样,Spring提供所有类型的通知,我们推荐你使用尽可能简单的通知类型来实现需要的功能。例如,如果你只是需要一个方法的返回值来更新缓存,最好使用后置通知而不是环绕通知,尽管环绕通知也能完成同样的事情。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。比如,你不需要在JoinPoint上调用用于环绕通知的proceed()方法,就不会有调用的问题。

3. AOP实现方式

Spring AOP 是通过动态代理技术实现的,而动态代理是基于反射设计的。Spring AOP 采用了两种混合的实现方式:

  • JDK 动态代理(interface):只能为接口创建代理对象,创建出来的代理都是java.lang.reflect.Proxy的子类;
  • CGLib 动态代理:cglib弥补了jdk动态代理的不足,jdk动态代理只能为接口创建代理,而cglib不管是接口还是类,都可以使用cglib来创建代理。cglib创建代理的过程,相当于创建了一个新的类(继承),可以通过cglib来配置这个新的类需要实现的接口,以及需要继承的父类。

详细介绍见 Spring系列之jdk动态代理和cglib代理

img

4. AOP使用

这里只介绍Spring AOP的使用方法,还有AspectJ也能实现AOP。

1.添加依赖: 在项目的pom.xml文件中添加 Spring AOP 依赖,以确保 AOP 模块可用。

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

2.创建切面类: 创建一个 Java 类,并使用@Aspect注解标记它,这个类将充当切面。

在切面类中定义通知方法,使用注解如@Before@After@Around等来指定在何时执行横切逻辑。

下面的切点会在执行controller的周围进行我们需要的操作。

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Aspect
@Component
public class MethodExecutionTimeAspect {

    private final static Logger LOG = LoggerFactory.getLogger(LogAspect.class);
  
    /** 定义一个切点 */
    @Pointcut("execution(* com.example.myapp.controller..*Controller.*(..))")

    @Before("controllerPointcut()")
    public void beforeServiceMethodExecution() {
        startTime = System.currentTimeMillis();
        // 打印请求信息
        LOG.info("------------- Begin -------------");
        LOG.info("Request method: {} {}", request.getRequestURL().toString(), request.getMethod());
        LOG.info("Class name: {}.{}", signature.getDeclaringTypeName(), name);
        LOG.info("Remote address: {}", request.getRemoteAddr());
    }

    @Around("controllerPointcut()")
    public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        // 执行程序
        Object result = proceedingJoinPoint.proceed();
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        LOG.info("Response: {}", JSONObject.toJSONString(result, excludefilter));
        LOG.info("------------- End time:{} ms -------------", System.currentTimeMillis() - startTime);
    }
}

参考文献

https://pdai.tech/md/spring/spring-x-framework-aop.html

https://apifox.com/apiskills/how-to-use-spring-boot-aop/

标签:连接点,Spring,编程,代理,切面,通知,AOP
From: https://www.cnblogs.com/TRY0929/p/17976652

相关文章

  • Spring AOP原来是这样实现的
    SpringAOP技术实现原理在Spring框架中,AOP(面向切面编程)是通过代理模式和反射机制来实现的。本文将详细介绍SpringAOP的技术实现原理,包括JDK动态代理和CGLIB代理的使用,并通过实例演示其在实际项目中的应用。1.AOP的实现原理概述SpringAOP的实现基于代理模式,通过代理对象来包......
  • A021 《斗图大赛》编程 源码
    一、课程介绍本节课将学习新的while循环,并结合布尔值True实现无限循环,最终实现一个动态表情包的效果。二、重难点解析布尔值在编程中,True是真,False是假。“真,假”,也是“对,错”的意思,它们是由英国著名数学家和逻辑学家乔治布尔提出的。所以,True和False也叫做布尔值,用于表示......
  • Python异步编程原理篇之协程的IO
    协程的IOasyncio作为实现异步编程的库,任务执行中遇到系统IO的时能够自动切换到其他任务。协程使用的IO模型是IO多路复用。在asyncio低阶API一篇中提到过“以Linux系统为例,IO模型有阻塞,非阻塞,IO多路复用等。asyncio常用的是IO多路复用模型的epool和kqueue”。本篇就介绍一......
  • 切面编程
    SpringBoot面向切面编程_springboot切面编程-CSDN博客SpringbootAOP切面编程_springboot切面编程-CSDN博客 切入点签名是什么意思切入点签名是一个包含名字和任意参数的方法签名,用于指定切入点和哪些方法进行匹配 。在AspectJ风格的AOP中,切入点签名采用一......
  • 元编程在 Python 的性能方面会有什么影响
    元编程是一种程序设计技术,它使得程序可以动态地创建和修改代码。Python作为一种动态语言,非常适合元编程。然而,使用元编程可能会对Python的性能产生一定的影响,本文将探讨这个问题。一、元编程的基本概念元编程是指在运行时创建、检查、操作和扩展程序的能力。Python中的元编程通常通......
  • 元编程在 Python 中有哪些应用场景
    元编程是一种强大而灵活的程序设计技术,允许我们在运行时动态地创建、检查、操作和扩展代码。在Python中,元编程可以发挥出其优势,并在许多应用场景中提供解决方案。本文将介绍一些常见的元编程应用场景,以帮助您更好地理解和利用这一技术。一、框架和库开发1.类装饰器:通过定义类装饰器......
  • 论文翻译 | 【深入挖掘Java技术】「底层原理专题」深入分析一下并发编程之父Doug Lea
    前提介绍DougLea在州立大学奥斯威戈分校(DougLea)摘要本文深入探讨了一个Java框架的设计、实现及其性能。该框架遵循并行编程的理念,通过递归方式将问题分解为多个子任务,并利用工作窃取技术进行并行处理。所有子任务完成后,其结果被整合以形成完整的并行程序。在总体设计上,该框架借鉴......
  • Python编程语法零基础入门
    0.开始前了解#号是一行注释"""6个"是多行注释"""#--coding:UTF-8print(u"你好!")#中文加上u转为unicode显示,不然会显示乱码1.基础语法和概念#(1)基本数据结构(整型、浮点型、字符串、布尔型)#格式:name=value没有分号、编译器自动匹配类型int_num=10float_num=......
  • Spring Boot入坑-AOP、Interceptor和Filter
    AOP概述面向切面编程(AspectOrientedProgramming),从不同的维度或角度给已有程序添加附加功能的一种技术实现的方式是Spring容器为程序创建代理,让调用方无感知的调用指定方法,在运行期间动态的“织入”其他逻辑主要目的是为了解耦弥补OOP中只能继承类或实现接口进行功......
  • 如何提升编程技术
    学习改变命运,技术铸就辉煌。大家好,我是銘,全栈开发程序员,今天在逛知乎的时候,看到一个话题,程序员的编程能力如何进阶。看了里面的回答,很有感触,那今天我就来聊一下程序员如何提升编程能力。多看源码很多新人一般都会遇到这种实实在在的问题,就是看了很多听了很多,但让自己上手写代码还......