一文带你搞定AOP切面

article/2025/9/21 14:15:40
摘要:AOP在spring中又叫“面向切面编程”,是对传统我们面向对象编程的一个补充,主要操作对象就是“ 切面”, 可以简单的理解它是贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。

本文分享自华为云社区《一篇文搞懂《AOP面向切面编程》是一种什么样的体验?》,作者: 灰小猿。

一、什么是Spring的AOP?

AOP在spring中又叫“面向切面编程”,它可以说是对传统我们面向对象编程的一个补充,从字面上顾名思义就可以知道,它的主要操作对象就是“切面”,所以我们就可以简单的理解它是贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。相当于是将我们原本一条线执行的程序在中间切开加入了一些其他操作一样。

在应用AOP编程时,仍然需要定义公共功能,但可以明确的定义这个功能应用在哪里,以什么方式应用,并且不必修改受影响的类。这样一来横切关注点就被模块化到特殊的类里——这样的类我们通常就称之为“切面”。

例如下面这个图就是一个AOP切面的模型图,是在某一个方法执行前后执行的一些操作,并且这些操作不会影响程序本身的运行。

AOP切面编程中有一个比较专业的术语,我给大家罗切出来了:

现在大概的了解了AOP切面编程的基本概念,接下来就是实际操作了。

二、AOP框架环境搭建

1、导入jar包

目前比较流行且常用的AOP框架是AspectJ,我们在做SSM开发时用到的也是AspectJ,使用该框架技术就需要导入它所支持的jar包,

  • aopalliance.jar
  • aspectj.weaver.jar
  • spring-aspects.jar

关于SSM开发所使用的所有jar包和相关配置文件我都已将帮大家准备好了!

点击链接下载就能用。【全网最全】SSM开发必备依赖-Jar包、参考文档、常用配置

2、引入AOP名称空间

使用AOP切面编程时是需要在容器中引入AOP名称空间的,

3、写配置

其实在做AOP切面编程时,最常使用也必备的一个标签就是,< aop:aspectj-autoproxy></aop:aspectj-autoproxy>,

我们在容器中需要添加这个元素,当Spring IOC容器侦测到bean配置文件中的< aop:aspectj-autoproxy>元素时,会自动为与AspectJ切面匹配的bean创建代理。
同时在现在的spring中使用AOP切面有两种方式,分别是AspectJ注解或基于XML配置的AOP,

下面我依次和大家介绍一下这两种方式的使用。

三、基于AspectJ注解的AOP开发

在上一篇文章中我也和大家将了关于spring中注解开发的强大,所以关于AOP开发我们同样也可以使用注解的形式来进行编写,下面我来和大家介绍一下如何使用注解方式书写AOP。

1、五种通知注解

首先要在Spring中声明AspectJ切面,只需要在IOC容器中将切面声明为bean实例。

当在Spring IOC容器中初始化AspectJ切面之后,Spring IOC容器就会为那些与 AspectJ切面相匹配的bean创建代理。

在AspectJ注解中,切面只是一个带有@Aspect注解的Java类,它往往要包含很多通知。通知是标注有某种注解的简单的Java方法。

AspectJ支持5种类型的通知注解:

  1. @Before:前置通知,在方法执行之前执行
  2. @After:后置通知,在方法执行之后执行
  3. @AfterRunning:返回通知,在方法返回结果之后执行
  4. @AfterThrowing:异常通知,在方法抛出异常之后执行
  5. @Around:环绕通知,围绕着方法执行

2、切入点表达式规范

这五种通知注解后面还可以跟特定的参数,来指定哪一个切面方法在哪一个方法执行时触发。那么具体操作是怎么样的呢?

这里就需要和大家介绍一个名词:“切入点表达式”,通过在注解中加入该表达式参数,我们就可以通过表达式的方式定位一个或多个具体的连接点,

切入点表达式的语法格式规范是:

execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名] ([参数列表]))

其中在表达式中有两个常用的特殊符号:

星号“ * ”代表所有的意思,星号还可以表示任意的数值类型

“.”号:“…”表示任意类型,或任意路径下的文件,

在这里举出几个例子:

表达式:

execution(* com.atguigu.spring.ArithmeticCalculator.*(…))

含义:

ArithmeticCalculator接口中声明的所有方法。第一个“”代表任意修饰符及任意返回值。第二个“”代表任意方法。“…”匹配任意数量、任意类型的参数。若目标类、接口与该切面类在同一个包中可以省略包名。

表达式:

execution(public * ArithmeticCalculator.*(…))

含义:

ArithmeticCalculator接口的所有公有方法

表达式:

execution(public double ArithmeticCalculator.*(…))

含义:

ArithmeticCalculator接口中返回double类型数值的方法

表达式:

execution(public double ArithmeticCalculator.*(double, …))

含义:

第一个参数为double类型的方法。“…” 匹配任意数量、任意类型的参数。

表达式:

execution(public double ArithmeticCalculator.*(double, double))

含义:

参数类型为double,double类型的方法

这里还有一个定位最模糊的表达式:

execution("* *(…)")

表示任意包下任意类的任意方法,但是这个表达式千万别写,哈哈,不然你每一个执行的方法都会有通知方法执行的!

同时,在AspectJ中,切入点表达式可以通过 “&&”、“||”、“!”等操作符结合起来。

如:

execution (* .add(int,…)) || execution( *.sub(int,…))

表示任意类中第一个参数为int类型的add方法或sub方法

3、注解实践

现在我们已经知道了注解和切入点表达式的使用,那么接下来就是进行实践了,

对于切入点表达式,我们可以直接在注解中使用“”写在其中,还可以在@AfterReturning注解和@AfterThrowing注解中将切入点赋值给pointcut属性,但是在其他的注解中没有pointcut这个参数。

将切入点表达式应用到实际的切面类中如下:

@Aspect	//切面注解
@Component	//其他业务层
public class LogUtli {
//	方法执行开始,表示目标方法是com.spring.inpl包下的任意类的任意以两个int为参数,返回int类型参数的方法@Before("execution(public int com.spring.inpl.*.*(int, int))")public static void LogStart(JoinPoint joinPoint) {System.out.println("通知记录开始...");}
//	方法正常执行完之后/*** 在程序正常执行完之后如果有返回值,我们可以对这个返回值进行接收* returning用来接收方法的返回值* */@AfterReturning(pointcut="public int com.spring.inpl.*.*(int, int)",returning="result")public static void LogReturn(JoinPoint joinPoint,Object result) {System.out.println("【" + joinPoint.getSignature().getName() + "】程序方法执行完毕了...结果是:" + result);}
}

以上只是一个最简单的通知方法,但是在实际的使用过程中我们可能会将多个通知方法切入到同一个目标方法上去,比如同一个目标方法上既有前置通知、又有异常通知和后置通知。

但是这样我们也只是在目标方法执行时切入了一些通知方法,那么我们能不能在通知方法中获取到执行的目标方法的一些信息呢?当然是可以的。

4、JoinPoint获取方法信息

在这里我们就可以使用JoinPoint接口来获取到目标方法的信息,如方法的返回值、方法名、参数类型等。

如我们在方法执行开始前,获取到该目标方法的方法名和输入的参数并输出。

//	方法执行开始@Before("execution(public int com.spring.inpl.*.*(int, int))")public static void LogStart(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();	//获取到参数信息Signature signature = joinPoint.getSignature(); //获取到方法签名String name = signature.getName();	//获取到方法名System.out.println("【" + name + "】记录开始...执行参数:" + Arrays.asList(args));}

5、接收方法的返回值和异常信息

对于有些目标方法在执行完之后可能会有返回值,或者方法中途异常抛出,那么对于这些情况,我们应该如何获取到这些信息呢?

首先我们来获取当方法执行完之后获取返回值,

在这里我们可以使用@AfterReturning注解,该注解表示的通知方法是在目标方法正常执行完之后执行的。

在返回通知中,只要将returning属性添加到@AfterReturning注解中,就可以访问连接点的返回值。

该属性的值即为用来传入返回值的参数名称,但是注意必须在通知方法的签名中添加一个同名参数。

在运行时Spring AOP会通过这个参数传递返回值,由于我们可能不知道返回值的类型,所以一般将返回值的类型设置为Object型。

与此同时,原始的切点表达式需要出现在pointcut属性中,如下所示:

//	方法正常执行完之后/*** 在程序正常执行完之后如果有返回值,我们可以对这个返回值进行接收* returning用来接收方法的返回值* */@AfterReturning(pointcut="public int com.spring.inpl.*.*(int, int)",returning="result")public static void LogReturn(JoinPoint joinPoint,Object result) {System.out.println("【" + joinPoint.getSignature().getName() + "】程序方法执行完毕了...结果是:" + result);}

对于接收异常信息,方法其实是一样的。

我们需要将throwing属性添加到@AfterThrowing注解中,也可以访问连接点抛出的异常。Throwable是所有错误和异常类的顶级父类,所以在异常通知方法可以捕获到任何错误和异常。

如果只对某种特殊的异常类型感兴趣,可以将参数声明为其他异常的参数类型。然后通知就只在抛出这个类型及其子类的异常时才被执行。

实例如下:

//	异常抛出时/*** 在执行方法想要抛出异常的时候,可以使用throwing在注解中进行接收,* 其中value指明执行的全方法名* throwing指明返回的错误信息* */@AfterThrowing(pointcut="public int com.spring.inpl.*.*(int, int)",throwing="e")public static void LogThowing(JoinPoint joinPoint,Object e) {System.out.println("【" + joinPoint.getSignature().getName() +"】发现异常信息...,异常信息是:" + e);}

6、环绕通知

我们在上面介绍通知注解的时候,大家应该也看到了其实还有一个很重要的通知——环绕通知

环绕通知是所有通知类型中功能最为强大的,能够全面地控制连接点,甚至可以控制是否执行连接点。

对于环绕通知来说,连接点的参数类型必须是ProceedingJoinPoint。它是 JoinPoint的子接口,允许控制何时执行,是否执行连接点。

在环绕通知中需要明确调用ProceedingJoinPoint的proceed()方法来执行被代理的方法。如果忘记这样做就会导致通知被执行了,但目标方法没有被执行。这就意味着我们需要在方法中传入参数ProceedingJoinPoint来接收方法的各种信息。

注意:
环绕通知的方法需要返回目标方法执行之后的结果,即调用 joinPoint.proceed();的返回值,否则会出现空指针异常。

具体使用可以看下面这个实例:

/*** 环绕通知方法* 使用注解@Around()* 需要在方法中传入参数proceedingJoinPoint 来接收方法的各种信息* 使用环绕通知时需要使用proceed方法来执行方法* 同时需要将值进行返回,环绕方法会将需要执行的方法进行放行* ********************************************** @throws Throwable * */@Around("public int com.spring.inpl.*.*(int, int)")public Object MyAround(ProceedingJoinPoint pjp) throws Throwable {//		获取到目标方法内部的参数Object[] args = pjp.getArgs();System.out.println("【方法执行前】");
//		获取到目标方法的签名Signature signature = pjp.getSignature();String name = signature.getName();Object proceed = null;try {
//			进行方法的执行proceed = pjp.proceed();System.out.println("方法返回时");} catch (Exception e) {System.out.println("方法异常时" + e);}finally{System.out.println("后置方法");}//将方法执行的返回值返回return proceed;}

7、通知注解的执行顺序

那么现在这五种通知注解的使用方法都已经介绍完了,我们来总结一下这几个通知注解都在同一个目标方法中时的一个执行顺序。

在正常情况下执行:

@Before(前置通知)—>@After(后置通知)---->@AfterReturning(返回通知)

在异常情况下执行:

@Before(前置通知)—>@After(后置通知)---->@AfterThrowing(异常通知)

当普通通知和环绕通知同时执行时:

执行顺序是:

环绕前置----普通前置----环绕返回/异常----环绕后置----普通后置----普通返回/异常

8、重用切入点定义

对于上面的通知注解,我们都是在每一个通知注解上都定义了一遍切入点表达式,

但是试想一个问题,如果我们不想给这个方法设置通知方法了,或者我们想要将这些通知方法切入到另一个目标方法,那么我们岂不是要一个一个的更改注解中的切入点表达式吗?这样也太麻烦了吧?

所以spring就想到了一个办法,重用切入点表达式

也就是说将这些会重复使用的切入点表达式用一个方法来表示,那么我们的通知注解只需要调用这个使用了该切入点表达式的方法即可实现和之前一样的效果,这样的话,我们即使想要更改切入点表达式的接入方法,也不用一个一个的去通知注解上修改了。

获取可重用的切入点表达式的方法是:

  1. 随便定义一个void的无实现的方法
  2. 为方法添加注解@Pointcut()
  3. 在注解中加入抽取出来的可重用的切入点表达式
  4. 使用value属性将方法加入到对应的切面函数的注解中

完整实例如下:

@Aspect	//切面注解
@Component	//其他业务层
public class LogUtli {/*** 定义切入点表达式的可重用方法* */@Pointcut("execution(public int com.spring.inpl.MyMathCalculator.*(int, int))")public void MyCanChongYong() {}//	方法执行开始@Before("MyCanChongYong()")public static void LogStart(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs();	//获取到参数信息Signature signature = joinPoint.getSignature(); //获取到方法签名String name = signature.getName();	//获取到方法名System.out.println("【" + name + "】记录开始...执行参数:" + Arrays.asList(args));}
//	方法正常执行完之后/*** 在程序正常执行完之后如果有返回值,我们可以对这个返回值进行接收* returning用来接收方法的返回值* */@AfterReturning(value="MyCanChongYong()",returning="result")public static void LogReturn(JoinPoint joinPoint,Object result) {System.out.println("【" + joinPoint.getSignature().getName() + "】程序方法执行完毕了...结果是:" + result);}//	异常抛出时/*** 在执行方法想要抛出异常的时候,可以使用throwing在注解中进行接收,* 其中value指明执行的全方法名* throwing指明返回的错误信息* */@AfterThrowing(value="MyCanChongYong()",throwing="e")public static void LogThowing(JoinPoint joinPoint,Object e) {System.out.println("【" + joinPoint.getSignature().getName() +"】发现异常信息...,异常信息是:" + e);}//	结束得出结果@After(value = "execution(public int com.spring.inpl.MyMathCalculator.add(int, int))")public static void LogEnd(JoinPoint joinPoint) {System.out.println("【" + joinPoint.getSignature().getName() +"】执行结束");}/*** 环绕通知方法* @throws Throwable * */@Around("MyCanChongYong()")public Object MyAround(ProceedingJoinPoint pjp) throws Throwable {//		获取到目标方法内部的参数Object[] args = pjp.getArgs();System.out.println("【方法执行前】");
//		获取到目标方法的签名Signature signature = pjp.getSignature();String name = signature.getName();Object proceed = null;try {
//			进行方法的执行proceed = pjp.proceed();System.out.println("方法返回时");} catch (Exception e) {System.out.println("方法异常时" + e);}finally{System.out.println("后置方法");}//将方法执行的返回值返回return proceed;}
}

以上就是使用AspectJ注解实现AOP切面的全部过程了,

在这里还有一点特别有意思的规定提醒大家,就是当你有多个切面类时,切面类的执行顺序是按照类名的首字符先后来执行的(不区分大小写)。

接下来我来和大家讲解一下实现AOP切面编程的另一种方法——基于XML配置的AOP实现。

四、基于XML配置的AOP实现

基于XML配置的AOP切面顾名思义就是摒弃了注解的使用,转而在IOC容器中配置切面类,这种声明是基于aop名称空间中的XML元素来完成的,

在bean配置文件中,所有的Spring AOP配置都必须定义在< aop:config>元素内部。对于每个切面而言,都要创建一个< aop:aspect>元素来为具体的切面实现引用后端bean实例。

切面bean必须有一个标识符,供< aop:aspect>元素引用。

所以我们在bean的配置文件中首先应该先将所需切面类加入到IOC容器中去,之后在aop的元素标签中进行配置。我们在使用注解进行开发的时候,五种通知注解以及切入点表达式这些在xml文件中同样是可以配置出来的。

1、声明切入点

切入点使用

< aop:pointcut>元素声明。
切入点必须定义在< aop:aspect>元素下,或者直接定义在< aop:config>元素下。

定义在< aop:aspect>元素下:只对当前切面有效

定义在< aop:config>元素下:对所有切面都有效

基于XML的AOP配置不允许在切入点表达式中用名称引用其他切入点。

2、声明通知

在aop名称空间中,每种通知类型都对应一个特定的XML元素。

通知元素需要使用< pointcut-ref>来引用切入点,或用< pointcut>直接嵌入切入点表达式。
method属性指定切面类中通知方法的名称

具体使用可以看下面这里实例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><!-- 通过配置文件实现切面 1、将目标类和切面类加入到容器中 @component2、声明哪个类是切面类,@Aspect3、在配置文件中配置五个通知方法,告诉切面类中的方法都何时运行4、开启基于注解的AOP功能--><!-- 将所需类加入到容器中 --><bean id="myCalculator" class="com.spring.inpl.MyMathCalculator"></bean><bean id="logUtil" class="com.spring.utils.LogUtli"></bean><bean id="SecondUtli" class="com.spring.utils.SecondUtli"></bean><!-- 进行基于AOP的配置 --><!-- 当有两个切面类和一个环绕方法时,方法的执行是按照配置文件中配置的先后顺序执行的配置在前的就会先执行,配置在后的就会后执行,但同时环绕方法进入之后就会先执行环绕方法--><aop:config><!-- 配置一个通用类 --><aop:pointcut expression="execution(public int com.spring.inpl.MyMathCalculator.*(int, int)))" id="myPoint"/><!-- 配置某一个指定的切面类 --><aop:aspect id="logUtil_Aspect" ref="logUtil"><!-- 为具体的方法进行指定method指定具体的方法名pointcut指定具体要对应的方法--><aop:before method="LogStart" pointcut="execution(public int com.spring.inpl.MyMathCalculator.add(int, int))"/><aop:after-throwing method="LogThowing" pointcut="execution(public int com.spring.inpl.MyMathCalculator.*(int, int)))" throwing="e"/><aop:after-returning method="LogReturn" pointcut-ref="myPoint" returning="result"/><aop:after method="LogEnd" pointcut-ref="myPoint"/><!-- 定义一个环绕方法 --><aop:around method="MyAround" pointcut-ref="myPoint"/></aop:aspect><!-- 定义第二个切面类 --><aop:aspect ref="SecondUtli"><aop:before method="LogStart" pointcut="execution(public int com.spring.inpl.MyMathCalculator.*(..))"/><aop:after-throwing method="LogThowing" pointcut-ref="myPoint" throwing="e"/><aop:after method="LogEnd" pointcut-ref="myPoint"/></aop:aspect></aop:config>
</beans>

总结一下通过XML配置实现AOP切面编程的过程:

通过配置文件实现切面

  1. 将目标类和切面类加入到容器中 相当于注解@component
  2. 声明哪个类是切面类,相当于注解@Aspect
  3. 在配置文件中配置五个通知方法,告诉切面类中的方法都何时运行
  4. 开启基于注解的AOP功能

这里有一点还需要注意:

当有两个切面类和一个环绕方法时,方法的执行是按照配置文件中配置的先后顺序执行的,配置在前的就会先执行,配置在后的就会后执行,但同时环绕方法进入之后就会先执行环绕方法。

最后总结

至此通过AspectJ注解和XML配置两种方式来实现AOP切面编程的过程就和大家分享完了,

总体来说基于注解的声明要优先于基于XML的声明。通过AspectJ注解,切面可以与AspectJ兼容,而基于XML的配置则是Spring专有的。由于AspectJ得到越来越多的 AOP框架支持,所以以注解风格编写的切面将会有更多重用的机会。

点击关注,第一时间了解华为云新鲜技术~


http://chatgpt.dhexx.cn/article/cOPbUyNa.shtml

相关文章

SpringBoot AOP切面实现

文章目录 一、AOP简介二、AOP体系与概念三、AOP实例1、创建SpringBoot工程2、添加依赖3、AOP相关注解3.1、Aspect3.2、Pointcut3.2.1、execution()3.2.2、annotation() 3.3、Around3.4、Before3.5、After3.6、AfterReturning3.7、AfterThrowing 一、AOP简介 AOP&#xff08;As…

AOP切面编程的理解

一、什么是Spring的AOP&#xff1f; AOP在spring中又叫“面向切面编程”&#xff0c;它可以说是对传统我们面向对象编程的一个补充&#xff0c;从字面上顾名思义就可以知道&#xff0c;它的主要操作对象就是“切面”&#xff0c;所以我们就可以简单的理解它是贯穿于方法之中&a…

AOP切面使用

一、主要设计注解&#xff1a; Aspect After before Pointcut Around pom文件引入 <!--用于aop切面编程--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> </dependency> 二、AOP核心…

AOP面向切面

1.什么是Spring的AOP? AOP又叫"面向切面编程",是对传统的面向对象编程的一个补充,主要的操作对象就是"切面 ",可以简单的理解它是贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。 相当于将我们原本一条线执行的程序在中间切…

【JavaEE】Spring AOP (面向切面)详解

目录&#xff1a; 1. 什么是 Spring AOP&#xff1f;1.1 AOP1.2 使用 AOP 的场景 2. AOP 组成2.1 切面&#xff08;Aspect&#xff09;2.2 连接点&#xff08;Join Point&#xff09;2.3 切点&#xff08;Pointcut&#xff09;2.4 通知&#xff08;Advice&#xff09; 3. AOP 概…

斜杠,反斜杠说明

/ 斜杠 \反斜杠 在window中都用斜杠 反斜杠是用来转译字符串的 eg: \"a\" 输出"a"

斜杠、反斜杠、双斜杠、反双斜杠的区别和使用方法及范围

背景 这边我就找了两篇大神写的文章&#xff0c;讲得非常清晰明了。文章主要讲了一些历史缘故和我们面对各种斜杠时的疑惑。 斜杠’/’ 和反斜杠’’ 深入探讨正斜杠和反斜杠 概念 1. 斜杠"/"是URL地址中用到的分隔符&#xff0c;并且在linux系统中的文件路径也是…

glob.glob()之返回路径的正反斜杆问题

Windows环境下用一个反斜杠就行 绝对路径&#xff1a;D:\PyCharm_code\pytorch_study\xxx 相对路径&#xff1a;.\cifar10_train\**\*.png 以下是踩过的坑&#xff1a;记录下

正反斜杠的区别_正斜杠( / )和反斜杠( \ )的区别

反斜杠“\”是电脑出现了之后为了表示程序设计里的特殊含义才发明的专用标点。所以除了程序设计领域外&#xff0c;任何地方都不应该使用反斜杠。 如何区分正反斜杠 英语&#xff1a;"/" 英文是forward slash, “\" 是backward slash 形象些比喻的话&#xff0c…

正斜杠 “/” 与反斜杠 “\”辨析

文章目录 1. 正斜杠 / / /2. 反斜杠 \ \backslash \3. 正斜杠与反斜杠的区别4. 注意 注意&#xff0c; / / / 为正斜杠(forward slash)&#xff0c;而 \ \backslash \ 为反斜杠(backward slash)。 1. 正斜杠 / / / 斜线是斜线标点符号 / / /。曾经用于标记句点和逗号的斜…

斜杠'/' 和反斜杠'\'

斜杠’/‘和反斜杠’\’ 2019-1-21 引言&#xff1a;从大一进入信息专业&#xff0c;正式接触计算机、代码也有几年了。一开始迷迷糊糊学Ascii码&#xff0c;很多特殊字符都需要转义&#xff0c;比如换行符\n&#xff0c;自那时起我就拎不清转义符是斜杠还是反斜杠&#xff0c;…

全面了解 Python 中的反斜杆

本文全面介绍了 Python 中反斜杆(\)的用法&#xff0c;包括原始字符串和普通字符串&#xff0c;repr() 和 str() ,\ 作为转义符&#xff0c;\ 作为续行符&#xff0c;\ 在字符串转义和正则表达式转义中的过程及注意事项等。阅读本文预计 6 min. 全面了解 Python 中的反斜杆 1. …

教你认识正斜杠(/)与反斜杠(\)

正斜杠&#xff0c;又称左斜杠&#xff0c;符号是 “/” ; 反斜杠&#xff0c;也称右斜杠&#xff0c;符号是 “” 。 经常很迷惑正斜杠与反斜杠到底有何区别&#xff1f;以下是一些总结: 背景了解 &#xff1a; DOS路径&#xff1a; C:\WINDOWS\SETTING …这是反斜杠的作用后…

微信支付,二维码图片解析

微信支付&#xff1a; 后台返回的是数据流&#xff1b; 开始这样&#xff0c;但是不行&#xff0c; 解决&#xff1a;在请求里面加入 ‘responseType’: ‘blob’ , 转换&#xff1a;附上base64转图片 //base64转换base64ImgtoFile(dataurl, filename file) {let arr data…

Apache里如何将图片解析成PHP

首先&#xff0c;如果没有安装PHP&#xff0c;先安装PHP yum install -y php然后进入网站根目录&#xff0c;如果不记得网站根目录&#xff0c;可以去配置文件里找 我的是/mnt/z 所以进入这个目录下&#xff0c;新建一个i.jpg文件 在浏览器里查看这个文件&#xff0c;存在错误…

图像解析力算法—SFR(Spatial Frequency Response)

Mitre SFR 1.4和sfrmat3是基于ISO 12233标准&#xff0c;但在某些方面彼此不同&#xff1a;Mitre SFR 1.4旨在尽可能接近标准&#xff0c; 而sfrmat3包含一些改进&#xff0c;可以获得精确的结果 即使被测试的图像质量极低。 M O R E MTF50&#xff0c;MTF50P 在表示相机图像…

JPEG图像格式解析

参考链接&#xff1a;jpeg图片格式详解_460833359的博客-CSDN博客_jpg文件通常是什么 一、JPEG图像介绍 jpg/jpeg是24位的图像文件格式&#xff0c;也是一种高效率的压缩格式&#xff0c;文件格式是JPEG&#xff08;联合图像专家组&#xff09;标准的产物&#xff0c;是面向连…

图像解析力算法—SFR(Spatial Frequency Response)概念理解

最近这一个月在搞SFR算法--&#xff08;空间频域响应&#xff09;&#xff0c;终于也算是搞出来了&#xff0c;网上关于SFR计算MTF的资料和博客也是比较少&#xff0c;现在就是总结一下&#xff0c;也算是方便后人&#xff0c;篇幅估计会比较长&#xff0c;会分篇慢慢写。 讲到…

DXF解析CAD图形解析PLT格式文件解析C#工程源码

DXF解析CAD图形解析PLT格式文件解析C#工程源码 激光切割机 雕刻机 打标机 写字机 巡边机 1.在文件菜单中选择打开dxf文件&#xff0c;算法会自动解析图形 2.解析完成后自动还原图形在界面显示 3.图形中的线条左边自动保存&#xff0c;在界面右侧工具栏选择开始加工按钮&…

Base64在线解析,编码转化为图片

博主介绍&#xff1a; 22届计科专业毕业&#xff0c;来自湖南&#xff0c;主要是在CSDN记录一些自己在Java开发过程中遇到的一些问题&#xff0c;欢迎大家一起讨论学习&#xff0c;也欢迎大家的批评指正。 前言 虽然我自己Base64在线解析用的少&#xff0c;但是避免不了需要使用…