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

【Spring】初识 Spring AOP(面向切面编程)

目录

1、介绍AOP

1.1、AOP的定义

1.2、AOP的作用

1.3、AOP的核心概念及术语

2、AOP实现示例

3、@EnableAspectJAutoProxy注解

1、介绍AOP

1.1、AOP的定义

        AOP(Aspect Orient Programming),直译过来就是面向切面编程,AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。AOP可以拦截指定的方法并且对方法增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离,比如Spring的事务,通过事务的注解配置,Spring会自动在业务方法中开启、提交业务,并且在业务处理失败时,执行相应的回滚策略。

1.2、AOP的作用

作用:AOP 采取横向抽取机制(动态代理),取代了传统纵向继承机制的重复性代码,其应用主要体现在事务处理、日志管理、权限控制、异常处理等方面。

主要作用是分离功能性需求和非功能性需求,使开发人员可以集中处理某一个关注点或者横切逻辑,减少对业务代码的侵入,增强代码的可读性和可维护性。

简单的说,AOP 的作用就是保证开发者在不修改源代码的前提下,为系统中的业务组件添加某种通用功能。

AOP的经典应用场景有:日志记录、事务管理、权限验证、性能监测

AOP可以拦截指定的方法,并且对方法增强,比如:事务、日志、权限、性能监测等增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离。

1.3、AOP的核心概念及术语

目标对象(Target):目标对象指将要被增强(比如增强功能)的对象,或者说被一个或多个切面所通知的对象,即包含主业务逻辑的类的对象,即为目标对象。

可以说要增强的对象(通常会有很多个)就是目标对象

切面(Aspect):指关注点模块化,这个关注点可能会横切多个对象。事务管理是企业级Java应用中有关横切关注点的例子。 在Spring AOP中,切面可以使用通用类基于模式的方式(schema-basedapproach)或者在普通类中以@Aspect注解(@Aspect注解方式)来实现。

可以说增强代码放入的那个类就叫切面类,由@Aspect注解来标识

通知(Advice):在切面的某个特定的连接点上执行的动作。通知有多种类型,包括“around”,“before” 和“after”等等。通知的类型将在后面详细了解。许多AOP框架,包括Spring在内,都是以拦截器做通知模型的,并维护着一个以连接点为中心的拦截器链。

用来放增强的代码的那个方法就是通知

  • 环绕通知@Around:可以把代码增强在目标方法的任意地方,更通用
  • 前置通知@Before:目标方法之前执行
  • 后置通知@After:目标方法之后执行
  • 异常通知@AfterThrowing:目标方法出现了异常执行
  • 返回通知@AfterReturning:目标方法返回值执行

切点(Pointcut):匹配连接点的断言。通知和切点表达式相关联,并在满足这个切点的连接点上运行(例如,当执行某个特定名称的方法时)。切点表达式如何和连接点匹配是AOP的核心:Spring默认使用Aspectj切点语义。

增强代码要对哪些类中的哪些方法进行增强,进行切割,指的是被增强的方法,即要切哪些东西。切点表达式

连接点(Join point):在Spring AOP中,一个连接点总是代表一个方法的执行,其实就代表增强的方法。

连接点就是通知和目标方法的一个桥梁,可以获取到目标方法的信息,就得通过JoinPoint

顾问(Advisor):顾问是Advice的一种包装体现,Advisor是Pointcut以及Advice的一个结合,用来管理Advice和Pointcut。应用无需关心.

顾问是源码中的体现,会封装切点和通知

织入(Weaving):将通知切入连接点的过程叫织入,就是我这个增强代码织入到目标方法或者叫切入到目标方法都可以

2、AOP实现示例

        假设有一个类的所有业务功能都已经实现,但是最后我想在所有的功能里面加一个公共的功能(记录所有的请求的用时), 这时候就可以利用AOP来实现,切面就是(需要增强的公共的、跟业务没有关系的公共代码)。可以在不改变原有业务代码的基础上进行了增强。所以面向切面编程往往让我们的开发更加低耦合,也大大减少了代码量,同时呢让我们更专注于业务模块的开发,把那些与业务无关的东西提取出去,便于后期的维护和迭代。

如何在Spring中创建一个所谓切面?

切面里面的代码怎么运行在业务方法(运行在之前、运行在之后)

使用AOP需要引入依赖

<!--以spring-boot-starter为前缀的依赖都是springboot官方提供的依赖,
不需要自己来指定版本,因为parent都帮我们管理好了,
springboot通过这种方式统一管理了版本,可以减少版本的冲突-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

aspectj:AOP概念并不是spring独家提出来的,AOP早就有成熟框架已经实现了,aspectj就是一个成熟的AOP的解决方案,spring只不过是把aspectj集成进来了

AOP实现示例代码:@Aspect注解可以把一个类标记为切面类

自定义类UserService,假设其所有业务功能(增删查改)都已经实现,但是我想给这些功能加一个记录请求用时的功能。这时用AOP来实现

//自定义类UserService,假设其所有业务功能都已经实现
@Service
public class UserService {// 增加增删改查方法,这里就用一个打印语句来代替具体的方法功能了public void add(){System.out.println("增加");}public void delete(){System.out.println("删除");}public void update(){System.out.println("修改");}public void query(){System.out.println("查询");}
}//切面类LogAspect,通过这个切面类来实现在所有的功能里面加一个公共的功能(记录所有的请求的用时)
@Aspect  //把这个类标记为切面类
@Component  //切面类必须声明为Spring的bean
public class LogAspect, {// execution(* com.lt.UserService.*(..)) 切点表达式// @Around 环绕通知@Around("execution(* com.lt.UserService.*(..))") //切点表达式public void log(ProceedingJoinPoint proceedingJoinPoint){//记录方法用时long begin = System.currentTimeMillis();// 执行具体的方法try {proceedingJoinPoint.proceed();} catch (Throwable e){System.out.println("方法执行异常:" + e.getMessage());}long end = System.currentTimeMillis();System.out.println("方法用时:" + (end - begin) + "ms");}}//测试类C4AopApplicationTests
@SpringBootTest(classes = C4AopApplicationTests.class)
@ComponentScan
class C4AopApplicationTests {@Testvoid contextLoads(@Autowired UserService userService) {userService.add();}}

运行结果:

3、@EnableAspectJAutoProxy注解

1、@EnableAspectJAutoProxy:启用AOP,没有这个注解AOP功能无法使用

如果要使用SpringAOP的功能,必须要添加一个@EnableAspectJAutoProxy注解,有了这个注解才能支持@Aspect等相关的一系列AOP注解的功能,这个注解就相当于在传统的xml配置文件中添加 <aop:aspectj-autoproxy>一样。

2、@EnableAspectAutoProxy不是一定要加的

比如上面的AOP示例,为什么没有加@EnableAspectJAutoProxy注解,AOP也起作用了?

这是因为SpringBoot其实会通过启动类自动帮我们加上@EnableAspectJAutoProxy,所以可以省略。(@SpringBootApplication这个注解帮我们做了很多的事情,包括自动帮我们加上@EnableAspectJAutoProxy注解)

//测试类C4AopApplicationTests
@SpringBootTest(classes = C4AopApplicationTests.class)
@ComponentScan
class C4AopApplicationTests {......
}//启动类
@SpringBootApplication // 由于这个注解起了作用,所以自动加了@EnableAspectJAutoProxy
public class C4AopApplication {......
}

所以com.lt包下的启动类C4AopApplication和他上面的上面的注解@SpringBootApplicatio也会被扫描到,由于这个注解起了作用,所以自动加了@EnableAspectJAutoProxy

但是依然建议加上@EnableAspectJAutoProxy,因为在Spring中没有这个注解AOP功能会无法使用。

 推荐:

【Spring】IOC/DI中常用的注解@Lazy、@Scope与@Conditional-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138277932?spm=1001.2014.3001.5501

【Spring】IOC/DI中常用的注解@Order与@DependsOn-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138167160?spm=1001.2014.3001.5501

【spring】Bean的生命周期回调函数和Bean的循环依赖-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_65277261/article/details/138503989?spm=1001.2014.3001.5501

http://www.lryc.cn/news/346247.html

相关文章:

  • k8s各个组件的作用
  • Spring Cloud 整合Sentinel
  • Java入门基础学习笔记4——开发Helloworld入门程序
  • 了解WebSocket
  • 从开发角度理解漏洞成因(02)
  • Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
  • TMS320F280049 CLB模块--LUT4 OUTLUT(4)
  • 功能测试_分类_用例_方法
  • [沫忘录]MySQL 锁
  • 噪声嵌入提升语言模型微调性能
  • XML文档基本语法
  • git开发工作流程
  • JDK生成https配置
  • 通过 Java 操作 redis -- set 集合基本命令
  • WebSocket前后端建立以及使用
  • C++数据结构之链表树图的存储
  • 又一位互联网大佬转行当网红,能写进简历么?
  • Codeforces Round 134 (Div. 1) A. Ice Skating (并查集)
  • 深入了解 Flask Request
  • 前端测试策略与实践:单元测试、E2E测试与可访问性审计
  • 修改el-checkbox样式
  • UE5缺少SDK,而无法在windows平台打包的解决方法
  • 4G,5G执法记录仪人脸识别、人脸比对使用说明
  • 掌握SEO优化的关键:提升网站排名的秘籍(如何提高网站seo排名)
  • 大模型微调之 在亚马逊AWS上实战LlaMA案例(九)
  • Php php7的特性
  • node pnpm修改默认包的存储路径
  • Adobe-Premiere-CEP 扩展 入门-视频剪辑-去气口插件-Silence Remover
  • 基于多目标灰狼算法的冷热电联供型微网低碳经济调度
  • Python 正则表达式 (?=...) 和 (?<=...) 符号