当前位置: 首页 > news >正文

Spring AOP全面详讲

目录

  • 一、Spring AOP的概念
    • 1、连接点JoinPoint
    • 2、通知Advice
    • 3、切入点PointCut
    • 4、切面Aspect
  • 二、xml文件实现AOP
    • 1、前置通知(before)
    • 2、后置通知
    • 3、返回通知
    • 4、异常通知
    • 5、环绕通知
  • 三、注解形式实现AOP

一、Spring AOP的概念

AOP:Aspect Oriented Programming(面向切面编程、面向方面编程),其实说白了,面向切面编程就是面向特定方法编程。

1、连接点JoinPoint

连接点的概念:可以被AOP控制的方法在SpringAOP提供的JoinPoint当中,封装了连接点方法在执行时的相关信息。

2、通知Advice

**通知:**指哪些重复的逻辑,也就是共性功能。
需要统计各个业务方法的执行耗时的,此时我们就需要在这些业务方法运行开始之前,先记录这个方法运行的开始时间,在每一个业务方法运行结束的时候,再来记录这个方法运行的结束时间。是在AOP面向切面编程当中,我们只需要将这部分重复的代码逻辑抽取出来单独定义。抽取出来的这一部分重复的逻辑,也就是共性的功能。

3、切入点PointCut

当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作。通过切入表达式找到切入点和通知进行配合。

4、切面Aspect

切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
当通知和切入点结合在一起,就形成了一个切面。通过切面就能够描述当前aop程序需要针对于哪个原始方法,在什么时候执行什么样的操作。
MAVEN项目如果需要使用AOP的情况,则需要再pom.xml文件中加入下面的依赖:

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.0.2.RELEASE</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.12</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!--AOP联盟--><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><!--Spring Aspects--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.0.2.RELEASE</version></dependency><!--aspectj--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version></dependency>

二、xml文件实现AOP

定义Cat类如下:

package com.example.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Cat {private String name;private int age;private void meow() {System.out.println("Meow!");}
}

定义People类如下:

package com.example.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {private String name;private int age;public void run(){System.out.println("running...");}
}

定义切面类如下:

package com.example.AOP;import org.aspectj.lang.annotation.Aspect;public class TestAOP {public static void yanzheng(){System.out.println(1);}
}

需要在spring.xml文件中定义如下:

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="people" class="com.example.entity.People"></bean><bean id="cat" class="com.example.entity.Cat"></bean><bean id="testAop" class="com.example.AOP.TestAOP"/><aop:config><aop:aspect ref="testAop"><aop:before method="yanzheng" pointcut="execution(* com.example.entity.People.run())"/></aop:aspect></aop:config>
</beans>

根据上面的代码可以知道,如果想使用AOP的时候需要将类和切面类都加入到IoC容器当中。即:
<bean id="people" class="com.example.entity.People"></bean> <bean id="cat" class="com.example.entity.Cat"></bean> <bean id="testAop" class="com.example.AOP.TestAOP"/>

<aop:aspect ref="testAop">

上面这个代码块配置的是配置切面类 ref指的是切面类的bean对象。

1、前置通知(before)

xml文件配置如下:

<aop:before method="yanzheng" pointcut="execution(* com.example.entity.People.run())"/>

测试类中的代码:

    @Testpublic void test1() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");People people = applicationContext.getBean("people", People.class);people.run();}

运行结果如下:
在这里插入图片描述
无论是否报错都会执行。

2、后置通知

<aop:after method="yanzheng" pointcut="execution(* com.example.entity.People.run())"/>

测试类运行结果如下:
在这里插入图片描述
无论是否报错都会执行。

3、返回通知

 <aop:after-returning method="yanzheng" pointcut="execution(* com.example.entity.People.run())"/>

测试代码:
在这里插入图片描述
当切入点方法有错误时,将没有返回值。对people做一下修改,迫使方法报错,修改如下:
在这里插入图片描述
重新测试结果:
在这里插入图片描述
没有出现返回值,所以after-returning只有代码正确,才会返回。

4、异常通知

 <aop:after-throwing method="yanzheng" pointcut="execution(* com.example.entity.People.run())"/>

当people类有错误的时候,代码执行结果如下:
在这里插入图片描述
After-throwing只有代码报错的时候才能执行。

5、环绕通知

<aop:around method="yanzheng" pointcut="execution(* com.example.entity.People.run())"/>

环绕通知会在切入方法的执行前运行,也会在切入方法执行后执行。因此通知方法需要做一下修改:

package com.example.AOP;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;public class TestAOP {public static void yanzheng(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(2+"我特殊");proceedingJoinPoint.proceed();System.out.println(1+"我是AOP");}
}

运行结果如下:
在这里插入图片描述

三、注解形式实现AOP

需要将通知方法的类上假日
@Controller
@Aspect

使其成为切面类
通知方法定义如下:

    @Around("execution(* com.example.entity.Cat.Meow())")public  void yanzheng1(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println(2+"我特殊");proceedingJoinPoint.proceed();System.out.println(1+"我是AOP");}@Before("execution(* com.example.entity.Cat.Meow())")public  void yanzheng2() {System.out.println(1+"我是AOP");}@After("execution(* com.example.entity.Cat.Meow())")public  void yanzheng3() {System.out.println(1+"我是AOP");}@AfterReturning("execution(* com.example.entity.Cat.Meow())")public  void yanzheng4() {System.out.println(1+"我是AOP");}@AfterThrowing("execution(* com.example.entity.Cat.Meow())")public  void yanzheng5() {System.out.println(1+"我是AOP");}

xml中的代码如下:

    <context:component-scan base-package="com.example.entity"></context:component-scan><context:component-scan base-package="com.example.AOP"></context:component-scan><aop:aspectj-autoproxy></aop:aspectj-autoproxy>

运行结果和第二节上面相同

http://www.lqws.cn/news/465877.html

相关文章:

  • 从 Elasticsearch 集群中移除一个节点
  • `customRef` 在实战中的使用:防抖、计算属性缓存和异步数据获取
  • 腾讯云IM即时通讯:开启实时通信新时代
  • nuxt3 + vue3 分片上传组件全解析(支持大文件+断点续传)
  • RabbitMQ 的工作流程
  • 【unitrix】 3.6 类型级数转基础类型(from.rs)
  • springboot通过独立事务管理器实现资源隔离与精准控制​
  • HTTPS的加密方式介绍
  • MinIO社区版文件预览失效?一招解决
  • 【Fargo】mediasoup发送2:码率分配、传输基类设计及WebRtcTransport原理
  • React 组件通信
  • C++ 移动构造:提升性能的利器
  • docker执行yum报错Could not resolve host: mirrorlist.centos.org
  • Snapchat矩阵运营新策略:亚矩阵云手机打造高效社交网络
  • C++:动态链接库的编写,__declspec 用法详解
  • 7.3.2_2平衡二叉树的删除
  • 【RTP】基于mediasoup的RtpPacket的H.264打包、解包和demo 1:不含扩展
  • windows下docker虚拟文件大C盘迁移D盘
  • GPT-1 与 BERT 架构
  • TodoList 案例(Vue3): 使用Composition API
  • 基于CNN-LSTM融合模型的环卫车动态称重算法研究:从频率感知到精准质量估计
  • 深入浅出JavaScript 中的代理模式:用 Proxy 掌控对象的“行为开关”
  • Python 爬虫案例(不定期更新)
  • Occt几何内核快速入门
  • Duende Identity Server学习之一:认证服务器及一个Oidc/OAuth认证、用于Machine 2 Machine的客户端
  • 在Docker、KVM、K8S常见主要命令以及在Centos7.9中部署的关键步骤学习备存
  • stm32移植freemodbus
  • C++ - vector 的使用
  • 【转】如何画好架构图:架构思维的三大底层逻辑
  • 使用 R 处理图像