动力节点Spring框架学习笔记-王鹤(二)AOP面向切面编程

2.1 概述

AOP(Aspect Orient Programming)。面向切面编程是从动态角度考虑程序运行过程

  • AOP 底层,就是采用动态代理模式实现的。采用了两种代理:JDK 的动态代理,与 CGLIB的动态代理,AOP就是动态代理的规范化, 把动态代理的实现步骤,方式都定义好了, 让开发人员用一种统一的方式,使用动态代理
  • Aspect: 切面,给你的目标类增加的功能,就是切面。 像上面用的日志,事务都是切面。切面的特点:一般都是非业务方法,独立使用的
  • Orient:面向, 对着
  • Programming:编程

2.2 相关术语

  1. Aspect:切面,表示增强的功能, 就是一堆代码,完成某个一个功能。非业务功能,常见的切面功能有日志, 事务, 统计信息, 参数检查, 权限验证,切面用于组织多个Advice,Advice放在切面中定义,实际就是对主业务逻辑的一种增强

  2. JoinPoint:连接点 ,连接业务方法和切面的位置。就某类中的业务方法,程序执行过程中明确的点,如方法的调用,或者异常的抛出。在Spring AOP中,连接点总是方法的调用

  3. Pointcut:切入点 ,指多个连接点方法的集合。多个方法。可以插入增强处理的连接点。简而言之,当某个连接点满足指定要求时,该连接点将被添加增强处理,该连接点也就变成了切入点

  4. Advice:AOP框架在特定的切入点执行的增强处理。处理有”around”、”before”和”after”等类型,能表示切面功能执行的时间,切入点定义切入的位置,通知定义切入的时间

  5. Target:目标对象,目 标 对 象 指 将 要 被 增 强 的 对 象 。 即 包 含 主 业 务 逻 辑 的 类 的 对 象

2.3 AspectJ

AspectJ是一个基于Java语言的AOP框架,提供了强大的AOP功能,其主要包括两个部分:

  • 一个部分定义了如何表达、定义AOP编程中的语法规范;
  • 另一个部分是工具部分,包括编译、调试工具等

aspectJ框架实现aop的两种方式:

  • @Before
  • @AfterReturning
  • @Around
  • @AfterThrowing
  • @After

表达式原型:

相关解释:

  • modifiers-pattern? 访问权限类型
  • ret-type-pattern 返回值类型
  • declaring-type-pattern? 包名类名
  • name-pattern(param-pattern) 方法名(参数类型和参数个数)
  • throws-pattern 抛出异常类型
  • ?表示可选的部分

以上表达式一共4个部分

execution(访问权限 方法返回值 方法声明(参数) 异常类型)

符号意义 *

相关实例:

  • execution(public * *(..)):任意公共方法
  • execution( set(..)):任何一个以”set”开始的方法
  • execution( com.xyz.service..*(..)):定义在 service 包里的任意类的任意方法
  • execution( com.xyz.service...(..)):定义在 service 包或者子包里的任意类的任意方法。”..”出现在类名中时,后面必须跟”“,表示包、子包下的所有类
  • execution( ..service..(..)):指定所有包下的 serivce 子包下所有类(接口)中所有方法为切入点
  • execution( com.xyz.service.IAccountService+.(..)):IAccountService 若为接口,则为接口中的任意方法及其所有实现类中的任意方法;若为类,则为该类及其子类中的任意方法
  • execution(* joke(String,int))):所有的 joke(String,int)方法,且 joke()方法的第一个参数是 String,第二个参数是 int;如果方法中的参数类型是 java.lang 包下的类,可以直接使用类名,否则必须使用全限定类名,如 joke( java.util.List, int)

1.方法的定义要求:

  • 公共方法 public
  • 方法没有返回值
  • 方法名称自定义
  • 方法可以有参数,也可以没有参数

2.@Before: 前置通知注解

属性:value ,是切入点表达式,表示切面的功能执行的位置

位置:在方法的上面

1.配置依赖

2.创建业务接口与实现类对象

3.创建切面类:MyAspect.java

4.配置applicationContext.xml文件

5.测试类调用

  • 指定通知方法中的参数 : JoinPoint
  • JoinPoint:业务方法,要加入切面功能的业务方法
  • 作用:可以在通知方法中获取方法执行时的信息, 例如方法名称,方法的实参
  • 如果需要切面功能中方法的信息,就加入JoinPoint
  • JoinPoint参数的值是由框架赋予, 必须是第一个位置的参数
  • 不止前置通知的方法,可以包含一个 JoinPoint 类型参数,所有的通知方法均可包含该参数

MyAspect.java

测试类

打印结果

  • 在目标方法执行之后执行
  • 由于是目标方法之后执行,所以可以获取到目标方法的返回值
  • 该注解的returning属性就是用于指定接收方法返回值的变量名的
  • 所以,被注解为后置通知的方法,除了可以包含 JoinPoint 参数外,还可以包含用于接收返回值的变量
  • 该变量最好为 Object 类型,因为目标方法的返回值可能是任何类型

业务方法

后置通知

1.该注解的 returning 属性就是用于指定接收方法返回值的变量名的

2.除了可以包含 JoinPoint 参数外,还可以包含用于接收返回值的变量

3.该变量最好为Object 类型,因为目标方法的返回值可能是任何类型

4.方法的定义要求:

  • 公共方法 public
  • 方法没有返回值
  • 方法名称自定义
  • 方法有参数的,推荐是Object ,参数名自定义

5.@AfterReturning:后置通知

  • value:切入点表达式
  • returning:自定义的变量,表示目标方法的返回值的,自定义变量名必须和通知方法的形参名一样
  • 可以根据业务方法的返回值做出相应的操作

测试类

在目标方法执行之前之后执行。被注解为环绕增强的方法要有返回值

被注解为环绕增强的方法要有返回值,Object 类型。并且方法可以包含一个ProceedingJoinPoint类型的参数

接口ProceedingJoinPoint其中有一个proceed() 方法,用于执行目标方法

若目标方法有返回值,则该方法的返回值就是目标方法的返回值。最后,环绕增强方法将其返回值返回。该增强方法实际是拦截了目标方法的执行

  • *切面类

1. 环绕通知方法的定义格式:

  • public
  • 必须有一个返回值,推荐使用Object
  • 方法名称自定义
  • 方法有参数,固定的参数 ProceedingJoinPoint

2. 特点

  • 在目标方法的前和后都能增强功能
  • 控制目标方法是否被调用执行
  • 修改原来的目标方法的执行结果,影响最后的调用结果
  • 它是功能最强的通知

3.环绕通知等同于jdk动态代理的InvocationHandler接口

4.参数:ProceedingJoinPoint 就等同于 Method,用于执行目标方法

5.返回值: 就是目标方法的执行结果,可以被修改

6.环绕通知:经常做事务, 在目标方法之前开启事务,执行目标方法, 在目标方法之后提交事务

测试类

在目标方法抛出异常后执行

该注解的 throwing 属性用于指定所发生的异常类对象

被注解为异常通知的方法可以包含一个参数 Throwable,参数名称为 throwing 指定的名称,表示发生的异常对象

  • *业务方法

  • *切面类

1. 异常通知方法的定义格式:

  • 访问权限public
  • 没有返回值
  • 方法名称自定义
  • 方法有个一个Exception, 也可以使用JoinPoint

2. @AfterThrowing:异常通知

  • 属性:

value 切入点表达式

throwinng 自定义的变量,表示目标方法抛出的异常对象,变量名必须和方法的参数名一样

  • 特点:

在目标方法抛出异常时执行的

可以做异常的监控程序, 监控目标方法执行时是不是有异常,如果有异常,可以发送邮件,短信进行通知

无论目标方法是否抛出异常,该增强均会被执行

  • *业务方法

切面类

  1. 最终通知的定义格式:

  2. 访问权限public

  3. 没有返回值
  4. 方法名称自定义
  5. 方法没有参数,但是可以使用JoinPoint

  6. @After :最终通知特点

  7. 总是会执行

  8. 在目标方法之后执行

当较多的通知增强方法使用相同的 execution 切入点表达式时,编写、维护均较为麻烦;AspectJ 提供了@Pointcut 注解,用于定义 execution 切入点表达式

将@Pointcut 注解在一个方法之上,以后所有的 execution 的 value 属性值均可使用该方法名作为切入点

代表的就是@Pointcut定义的切入点。这个使用@Pointcut注解的方法一般使用 private 的标识方法,即没有实际作用的方法

  • *切面类

1.@Pointcut: 定义和管理切入点, 如果你的项目中有多个切入点表达式是重复的,可以复用的。

2.特点:

当使用@Pointcut定义在一个方法的上面 ,此时这个方法的名称就是切入点表达式的别名

其它的通知中,value属性就可以使用这个方法名称,代替切入点表达式了

2.4 代理方式更换

如果目标类有接口,默认使用jdk动态代理,如果目标类没有接口,则使用CGlib动态代理

如果想让具有接口的目标类使用CGlib的代理方式,需要以下配置文件

Original: https://www.cnblogs.com/laoduyyds/p/15830873.html
Author: 老杜铁杆粉丝
Title: 动力节点Spring框架学习笔记-王鹤(二)AOP面向切面编程

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579922/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 基于Nacos实现GateWay动态路由功能

    开发环境: SpringBoot: 2.6.5 SpringCloud: 2021.0.0 SpringCloudAlibaba: 2021.0.1.0 Nacos: 2.1.0 …

    Java 2023年6月5日
    076
  • Django 前后台的数据传递

    Django 从后台往前台传递数据时有多种方法可以实现。 最简单的后台是这样的: 这个就是返回index.html的内容,但是如果要带一些数据一起传给前台的话,该怎么办呢? 这里是…

    Java 2023年5月29日
    067
  • Centos8安装MySQL8.0报错Failed to download metadata for repo‘AppStream’「CentOS」

    CentOS Linux 8 已于 2021 年 12 月 31 日结束生命周期 (EOL)。这意味着 CentOS 8 将不再从 CentOS 官方项目获得开发资源。在 2021…

    Java 2023年6月13日
    059
  • 《码处高效:Java开发手册》之代码风格

    流水淡,碧天长,鸿雁成行。编码风格,简捷清爽,反引无限风光。 在美剧《硅谷》中有这样一个经典镜头,主人公 Richard 与同为开发工程师的女友闹分手,理由是两人对缩进方式有着截然…

    Java 2023年6月5日
    066
  • 分布式缓存

    1.Redis持久化 Redis有两种持久化方案: RDB持久化 AOF持久化 1.1.RDB持久化 RDB全称Redis Database Backup file(Redis数据…

    Java 2023年6月9日
    074
  • Java Json

    读前需要了解 思路过程: 如果您的JSON很小,那么对象模型很好,因为您可以加载所有数据并作为普通Java对象工作。当文件非常大时,您可能不想加载它全部进入内存。 因此流和对象模型…

    Java 2023年5月29日
    078
  • 重定向与请求转法的区别(简洁版)

    TOC # 二者的定义 ## 重定向redirect 浏览器向服务器发送一个请求,服务器会接收并处理返回新处理的URL给,浏览器客户端,浏览器客户端再次请求服务器获取,服务器再次响…

    Java 2023年6月5日
    069
  • Java 基础(Optional类)

    Optional提供很多有用的方法,这样我们就不用显式进行空值检测。 OptionalTest.java package com.klvchen.java4; import org…

    Java 2023年5月29日
    076
  • Java学习-第一部分-第一阶段-第七节:面向对象编程(中级)

    面向对象编程(中级) 笔记目录:(https://www.cnblogs.com/wenjie2000/p/16378441.html) lntelliJ IDEA ●IDEA介绍…

    Java 2023年6月16日
    089
  • 【Feign】OpenFeign入门以及部分源码解析

    一、OpenFeign介绍 OpenFeign是⼀种声明式,模版化的HTTP客户端。使⽤OpenFeign进⾏远程调⽤时,开发者完全感知不到这是在进⾏远程调⽤,⽽是像在调⽤本地⽅法…

    Java 2023年6月8日
    069
  • JAVA中创建线程池的五种方法及比较

    之前写过JAVA中创建线程的三种方法及比较。这次来说说线程池。 JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用…

    Java 2023年5月29日
    090
  • 【spring boot】注解@ApiParam @PathVariable @RequestParam三者区别

    1.@ApiParam,就是用于swagger提供开发者文档,文档中生成的注释内容。 2.@RequestParam,是获取前端传递给后端的参数,可以是get方式,也可以是post…

    Java 2023年5月29日
    095
  • 线程安全问题

    线程安全问题 本篇主要讲解 线程安全问题,演示什么情况下会出现线程安全问题,以及介绍了 Java内存模型 、volatile关键字 、CAS 等 ,最后感谢吴恒同学的投稿! 一起来…

    Java 2023年6月9日
    074
  • SpringCloud架构系统中如何保证集群环境下定时任务同时只有一个实例运行工作?

    问题 首先说下情况,我们平常开发SpringCloud微服务的时候,若要确保高可用,同一服务都会部署多台实例,然后注册到Eureka上。 一般我们会把所有定时任务写到一个服务里,那…

    Java 2023年5月30日
    075
  • Java异常

    1.异常引入 package exception; @SuppressWarnings({"all"}) /** * @Author Blueshadow * …

    Java 2023年6月8日
    077
  • 调试webpack

    调试webpack 1. 摘要 用过构建工具webpack的朋友应该都体会,面对其几百行的配置内容如大海一小舟,找不到边。看文档查百度,对其构建的生命周期看了又看。最终还是很茫然。…

    Java 2023年6月13日
    057
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球