10. Spring-AOP的实现

本文最后更新于2023.11.30-17:38,某些文章具有时效性,若有错误或已失效,请在下方留言或联系涛哥

AOP的概念

Aspect Oreinted Programming 面向切面编程,通过预编译方式或者运行时动态代理的方式,实现程序功能的统一管理和维护的一种技术(AOP是一种思想,并不依赖于某个框架或者编程语言实现)。

为什么使用AOP?

利用AOP可以对 业务逻辑的各部分进行隔离,使程序员更加专注于业务核心逻辑,从而降低代码的耦合度,提供程序可重用性,提高开发的效率(主要应用场景:权限控制,日志记录,性能统计,事务管理,异常处理)

AOP相关的术语

1.目标对象

指需要被 增强的对象,Spring Aop通过代理增强实现 (target)

2.连接点(JoinPoint)

指的是被切面拦截到的点,在Spring当中指的是具体的方法.

3.切入点(pointcut)

表示一组连接点,通过正则表达式,通配符,aspectj切点表达式来进行定义和集中,定义了通知(advice)将要发生的地方. 简单的说:切入点就是我们对 哪些连接点 进行拦截的 定义。

4.通知:(advice)

通知指的是 拦截到连接点之后 要做的事情就是通知(功能增强) 按照分类:前置通知,后置通知,异常通知,环绕通知,最终通知。 前置通知:在目标对象的业务逻辑功能执行之前,发生. 通常用于:日志记录 权限控制

  • 后置返回通知:发生目标功能对象的业务逻辑正常执行完之后,发生. 通常用于:对方法返回值进行处理.
  • 后置异常通知:在目标对象的业务逻辑发生异常时发生 通常用于:项目的异常日志.
  • 后置:不管目标对象的业务逻辑是否发异常,都会被执行. 通常用于:资源释放.
  • 环绕通知:(使用最多),在目标对象的业务逻辑执行之前和之后发生。 通常用于:性能监控,事务管理.

顺序:环绕前置­­>普通前置­­>目标方法执行­­>环绕正常结束/出现异常­­>环绕后置­­>普通后置­­>普通返回或者异常。

5.切面: 切面指的是切入点(多个)和通知(多个)的结合

Spring Aop的实现

a.传统的Spring Aop编程(会在 通知 所使用的类中,实现各种接口,造成代码污染,不推荐)

b.Spring 整合AspectJ框架 实现aop

c.步骤:

1导入jar包(IOC相关 aop aopalliance aspectj相关jar包 ) org.aopalliance org.aspectj/weawer

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
​
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
​
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

 2在配置文件中,配置aop相关的命名空间 context 在文档中搜索 the aop schema

<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
        <context:component-scan base-package="com.edu.*"></context:component-scan>
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

3.创建目标.

4.创建通知.

5.在配置文件中进行配置 或者(使用注解)

5-1.把目标和通知 都进行bean的相关配置(注解)

5-2.使用aop:config 来进行面向切面的配置

5-3.在config中 使用aop:aspect表示一个切面 补充ref属性 指定通知使用的类的bean的名字(id)

5-4.在aspect中 使用<aop:pointcut /> 表示一个切点 在pointcut标签中 使用expression属性 去定义(集合) 一个切点 通常该属性的值是一个 aspectj切点表达式 ps:Spring中对aspectj的切点表达式,只是部分支持,并不支持全部的表达式. aspectJ常用的切点表达式: execution(public * *) 表示切点是 所有的public方法.

execution(* com.demo.service.*(..))表示 service包下的所有的类的 任意参数的任意方法.(不包含子包)
(..)表示 方法的参数个数类型 任意

execution(* com.demo.service..*(..))表示service包下(包含子包)的所有类的....

execution(* com.demo.service.impl.UserServiceImpl.*(..)) 表示UserServiceImpl下的所有方法

execution(* com.demo.service..*.add*(..)) 表示Service下所有包和子包中的 以add开头的方法
(自习:spring支持的aspectj 切点表达式)

5-5.配置前置通知: <aop:before method="指定通知的方法" pointcut="指定切点(切点表达式)" pointcut-ref="切点的Id"> 对于前置通知的方法 可以在方法中加入(Joinpoint参数 jt) 可以用来获取 连接点的目标对象 和 连接点的方法名 jt.getSignature().getName() 获取连接点方法的名字 jt.getSignature().getDeclaringTypeName() 获取连接点的目标对象

5-6.配置后置通知: <aop:after-returning method="" pointcut-ref="" returning="用于定义通知中 代表 业务逻辑返回值 的参数 名"> ps:通知的方法中 参数的名字要和returning的字符串一-cut 也可以使用JoinPoint的参数

5-7.最终通知: <aop:after method="" pointcut-ref="">

5-8.环绕通知: <aop:around method="" pointcut-ref="">

5-9.异常通知: <aop:after-throwing method="" pointcut-ref="" throwing=""> throwing用于规定 通知的方法中 表示业务逻辑抛出的异常 的 参数名.

使用注解去配置一个切面

1.需要配置 切面 切点 通知 切面的bean 业务逻辑类步骤:

1-1.在applicationContext中 加入 <aop:aspectj-autoproxy />配置 表示开启aspectj的自动代理功能.

1-2.在通知所在的类上 配置一个切面 @Aspect注解 ps:Aspect注解 用于修饰一个Spring的bean,保证通知不会对 这 个bean 本身进行增强

在方法切面的方法上 使用@Before 表示该方法是一个前置通知 before注解 需要添加 切点 @Before("execution(* com.demo.service..*(..))")

@Pointcut(切点表达式) 去表示一个切点. @Pointcut("execution(* com.demo.service..*(..))") public void mypointcut(){} 表示切点的方法 返回值一定是void 不需要方法参数和方法体 切点的名字 就是方法的名字

@AfterReturning(pointcut="切点",returning="业务逻辑方法 返回值的 参数名")表示一个 后置通知

后置通知中 可以的方法 可以加入两个参数:Joinpoint 表示连接点,还可以加入一个 Object 表示 业务方法的原始返回值. 一旦增加了 Object 那么要求 必须在 AfterReturning里 加入 returning="指定 返回值在通知方法中的形参的名字"。

@After("mypointcut") 表示一个最终通知

@AfterThrowing(pointcut="mypointcut()",throwing="e") 后置返回异常通知的方法 也可以加入两个参数:

Jointpoint 连接点 Exception e 表示 业务方法抛出的异常对象,一旦申明,必须在注解中 加入 throwing="e"

@Around("mypointcut") 修饰一个 环绕通知 修饰的方法 必须返回一个Object,方法中需要 ProceedingJoinPoint pjp类型的参数 pjp.proceed() 保证了 业务逻辑方法的执行.

PS:如果一个切点 被多个切面拦截,会先执行所有切面的前置通知 然后是环绕 .如果需要改变各个切面的优先级需要使用 @Order注解 可以在order中使用一个整形的属性 数值越小,说明该切面的优 先级越高

作业

要求:有UserDao AdminDao ProductDao使用 SpringAOP 完成以下功能

1 Dao层所有的方法在 执行前 提示 由SpringAOP 进行了增强

2 对于所有的 添加方法 计算 添加的用时 并打印

3 对于所有的删除方法 要求在抛出异常时 打印时间 方法 异常类型(自行在 对应的删除里面 产生各种异常)

4 对于 UserDao和ProductDao的所有方法在执行时 判断权限是否足够。

来源:百度网盘 | 提取码:d0dn

版权声明:
作者:涛哥
链接:https://ltbk.net/back/allspring/spring/article/404.html
来源:涛哥博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
10. Spring-AOP的实现
本文最后更新于2023.11.30-17:38,某些文章具有时效性,若有错误或已失效,请在下方留言或联系涛哥。AOP的概念 Aspect Oreinted Programming 面向切面编程,通……
<<上一篇
下一篇>>
文章目录
关闭
目 录