当前位置: 首页 > 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.lryc.cn/news/573525.html

相关文章:

  • Python 爬虫案例(不定期更新)
  • 一,python语法教程.内置API
  • 【知识图谱提取】【阶段总结】【LLM4KGC】LLM4KGC项目提取知识图谱推理部分
  • Linux 内核中 TCP 协议栈的输出实现:tcp_output.c 文件解析
  • 【JAVA】数组的使用
  • 电子电气架构 --- 实时系统评价的概述
  • 基于YOLO的智能车辆检测与记录系统
  • Transformer架构每层详解【代码实现】
  • LangGraph--基础学习(工具调用)
  • 2025zbrush雕刻笔记
  • NW849NX721美光固态闪存NX745NX751
  • 微处理器原理与应用篇---计算机系统的结构、组织与实现
  • 给交叉工具链增加libelf.so
  • 操作系统内核态和用户态--2-系统调用是什么?
  • 嵌入式开发之嵌入式系统架构如何搭建?
  • 【软考高级系统架构论文】论面向服务架构设计及其应用
  • modelscope设置默认模型路径
  • python的校园兼职系统
  • Taro 跨端开发:从调试到发布的完整指南
  • 基于正点原子阿波罗F429开发板的LWIP应用(7)——MQTT
  • 华为OD机试-云短信平台优惠活动-完全背包(JAVA 2024E卷)
  • TodoList 案例(Vue3): 使用Composition API
  • 嵌入式开发之嵌入式系统硬件架构设计时,如何选择合适的微处理器/微控制器?
  • 腾讯云IM即时通讯:开启实时通信新时代
  • 一文详解归并分治算法
  • Python:.py文件如何变成双击可执行的windows程序?(版本1)
  • 深入Java面试:从Spring Boot到微服务
  • Django数据库迁移
  • P1220 关路灯
  • Spring Boot + MyBatis + Vue:全栈开发的深度剖析与实践指南