Spring 6【方法参数校验、SpingAOP介绍、Schema-based方式实现AOP 】(十四)-全面详解(学习总结---从入门到深化)

news2024/9/26 5:22:16

 

目录

4.方法参数校验

SpingAOP介绍

Schema-based方式实现AOP 


4.方法参数校验

Spring框架提供了一种校验方法参数的方法,在调用一个方法传入参数后,会判断参数是否满足数据校验。如果满足方法执行,如果不满足:不执行方法,报异常。这和上面是不一样的。并且不需要使用 LocalValidatorFactoryBean 。

方法参数校验的核心有三点:

1、IoC容器中必须有MethodValidationPostProcessor这个Bean。默认没有,需要我们手动配置

2、需要进行方法校验的类上需要有@Validated注解

3、需要校验的方法参数前面需要有@Valid注解

4.1 新建类,添加校验注解 

我们还是用Student类,并在属性中添加校验

@Data
public class Student {
   @NotBlank
   private String name;
   @Positive
   private int age;
}

4.2 新建类,添加方法

新建com.tong.validation.StudentServiceImpl类,并添加注解

@Validated // 重要
public class StudentServiceImpl{
    public void student(@Valid Student stu){// @Valid 重要
    System.out.println("执行了这个方法");
   }
}

 4.3 新建配置文件

新建配置文件applicationContext-methodvalidation.xml 在配置文件中配置MethodValidationPostProcessor和StudentServiceImpl的Bean。 此功能和LocalValidatorFactoryBean无关,不需要配置LocalValidatorFactoryBean的Bean。

<bean id="studentServiceImpl" class="com.tong.validation.StudentServiceImpl"></bean>

<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcess
or"></bean>

 4.4 新建测试类

新建com.tong.test.ValidationMethodTest测试类

@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-methodvalidation.xml")
public class ValidationMethodTest {
      @Autowired
      StudentServiceImpl studentService;
      
      @Test
      void test(){
           Student stu = new Student();
           studentService.student(stu);
     }
}

 4.5 查看运行效果

在控制台报异常。

jakarta.validation.ConstraintViolationException: student.arg0.age: 必须是正数,
student.arg0.name: 不能为空

4.6 校验通过写法

给Student对象的属性设置上值,让校验通过。重新运行后,发现方法成功被调用。

@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-methodvalidation.xml")
public class ValidationMethodTest {
     @Autowired
     StudentServiceImpl studentService;
     @Test
     void test(){
         Student stu = new Student();
         stu.setName("smallming");//新加
         stu.setAge(16);// 新加
         studentService.student(stu);
    }
}

SpingAOP介绍

1.SpringAOP介绍

AOP(Aspect-oriented Programming,面向切面编程)并不是Spring框架提出的。而是AOP联盟组织的 一套规范。Spring AOP属于对AOP规范的一个具体实现。 我们先看看Spring官方对Spring AOP的解释。

官方说明:

翻译含义: 

面向切面编程 (AOP) 通过提供另一种思考程序结构的方式来补充面向对象编程 (OOP)。OOP 中模块化的关键单位是类,而 AOP 中模块化的单位是切面。切面能够实现跨越多种类型和对象的关注点(例如事务 管理)的模块化.(这种关注点在 AOP 文献中通常被称为“横切”关注点。) Spring 的关键组件之一是 AOP 框架。虽然 Spring IoC 容器不依赖于 AOP(意味着如果您不想使用 AOP,则不需要使用 AOP),但 AOP 补充了 Spring IoC 以提供一个非常强大的中间件解决方案。

下面对上面官方解释的总结:官方在强调AOP时强调了下面几点:

      1. AOP 叫做面向切面编程

      2. AOP 是对OOP的补充

      3. AOP的核心是切面

      4. AOP是依赖IoC

      5. AOP可以让多个类型和对象以模块化的方式形成横切面。 

所以AOP的解释:AOP是面向切面编程。可以对程序中方法进行扩展,且扩展内容和目标方法是松耦合 的(无论对目标方法还是对客户端,扩展后都是无感知的)、模块化的。 

想要把AOP解释清楚,就必须把AOP中的专业术语搞清楚。

 

Aspect:切面。即join point + Advice

join point: 切入点。就是我们平时说的目标方法,或说对哪个方法做扩展,做增强。

Advice:通知,增强内容。

Pointcut:切点。就是表达式,通过表达式说明哪些方法是join point

AOP Proxy:代理。Spring支持JDK动态代理和cglib动态代理两种方式,可以通过proxy-target-class=true把默认的JDK动态代理修改为Cglib动态代理。

Weaving:织入。织入就是把Advice添加到join point的过程。

在实际开发中AOP主要应用在Service层。 

 

Schema-based方式实现AOP 

1.实现AOP的两种方式

在Spring中提供了两种方式实现AOP:

  •       Schema-based:所有的通知都需要实现特定类型的接口。
  •       AspectJ:可以使用普通Java类结合特定的配置标签实现通知。

无论使用哪种方式在项目中都需要导入spring-aop和aspectjweaver两个依赖。

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>6.0.6</version>
</dependency>
<dependency>
     <groupId>org.aspectj</groupId>
     <artifactId>aspectjweaver</artifactId>
     <version>1.9.19</version>
</dependency>

 2.在Schema-based方式中通知的分类

  • 前置通知:在切入点之前执行的增强功能。通知需要实现MethodBeforeAdvice接口
  • 后置通知:在切入点之后执行的增强功能。通知需要实现AfterReturningAdvice接口
  • 环绕通知:一个方法包含了前置通知和后置通知的功能。通知需要实现MethodInterceptor接口
  • 异常通知:如果切入点中出现了异常(绝对不能try...catch解决了异常)就会触发异常通知。通知 需要实现ThrowsAdvice接口。

3. 前置通知 

前置通知是在切入点之前执行的增强。 在项目中保证有Spring框架最基本环境依赖以外,还需要打入aspectj依赖

<dependencies>
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>6.0.6</version>
   </dependency>
   <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.19</version>
   </dependency>
   <!-- 单元测试 -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>6.0.6</version>
   </dependency>
   <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.9.2</version>
      <scope>test</scope>
   </dependency>
   <!-- lombok 支持 @Data等注解 -->
   <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.26</version>
      <scope>provided</scope>
   </dependency>
</dependencies>

3.1 新建通知类

新建com.bjsxt.advice.MyBefore。

MethodBeforeAdvice接口中必须重写before方法,方法中三个参数:

  • method:切入点方法对象
  • args:切入点方法参数
  • target:切入点方法所在的对象
package com.tong.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class MyBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
          System.out.println("前置通知");
    }
}

3.2 配置切面

<?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
       https://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.tong.mapper,com.tong.service.impl"> 
    </context:component-scan>
    <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
      <aop:config>
      <!-- 切入点是固定语法:execution(* 方法的全限定路径带有参数) -->
      <!-- 无参方法:test()-->
      <!-- 有参方法:test(int,java.lang.String)-->
      <!-- 如果希望把所有叫做test的方法都匹配上,不考虑参数test(..)-->
      <!-- 全限定路径的层数绝对不能少,但是如果希望对类或包做统配使用*-->
      <!-- com.tong.service.impl.*.*(..)-->
        <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test())"/>
       <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"></aop:advisor>
       </aop:config>
</beans>

4. 后置通知

后置通知是在切入点之后执行的增强。

4.1 新建通知类

新建com.bjsxt.advice.MyAfter。 AfterReturningAdvice接口中必须重写afterReturning方法,方法中四个参数:

  • returnValue:返回值
  • method:切入点方法对象
  • args:切入点方法参数
  • target:切入点方法所在的对象
package com.tong.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class MyAfter implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args,Object target) throws Throwable {
         System.out.println("后置通知");
     }
}

4.2 配置切面

<?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
       https://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.tong.mapper,com.tong.service.impl"> 
    </context:component-scan>
    <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
    <!-- 配置后置通知bean -->
    <bean id="myafter" class="com.tong.advice.MyAfter"></bean>
    <aop:config>
       <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test())"/>
      <aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"></aop:advisor>
      <!-- 织入后置通知 -->
      <aop:advisor advice-ref="myafter" pointcut-ref="mypoint"></aop:advisor>
    </aop:config>
</beans>

5. 环绕通知

环绕通知可以实现前置通知和后置通知两种功能。

5.1 新建通知类

新建com.tong.advice.MyAround。

MethodInterceptor接口中必须重写invoke方法,方法中参数:

  • invocation:方法调用器。通过invocation可以proceed()方法调用执行点。 
package com.tong.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyAround implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
         System.out.println("环绕通知-前置增强");
         Object result = invocation.proceed();// 执行切入点
         System.out.println("环绕通知-后置增强");
         return result;
      }
}

 5.2 配置切面

<?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
       https://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.tong.mapper,com.tong.service.impl"> </context:component-scan>
     <bean id="mybefore" class="com.tong.advice.MyBefore"></bean>
     <bean id="myafter" class="com.tong.advice.MyAfter"></bean>
     <!-- 配置环绕通知bean -->
     <bean id="myaround" class="com.tong.advice.MyAround"></bean>
         <aop:config>
             <aop:pointcut id="mypoint" expression="execution(* com.tong.service.impl.PeopleServiceImpl.test())"/>
             <!-- 只织入环绕,没有织入前置通知和后置通知。 -->
             <aop:advisor advice-ref="myaround" pointcut-ref="mypoint"></aop:advisor>
         </aop:config>
</beans>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/809503.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android跨进程传大图思考及实现——附上原理分析

1.抛一个问题 这一天&#xff0c;法海想锻炼小青的定力&#xff0c;由于Bitmap也是一个Parcelable类型的数据&#xff0c;法海想通过Intent给小青传个特别大的图片 intent.putExtra("myBitmap",fhBitmap)如果“法海”(Activity)使用Intent去传递一个大的Bitmap给“…

win10中CUDA cundnn pytorch环境搭建记录

关于在win10中安装cuda cudnn及pytorch全家桶(torch torchvision torchaudio)的详细安装步骤&#xff0c;可以参考这个帖子&#xff0c;说的非常详细&#xff01; win10下pytorch-gpu安装以及CUDA详细安装过程 仅在此记录一下我的两台电脑安装的环境 目录 一、笔记本环境配置1.…

Leetcode-每日一题【剑指 Offer II 009. 乘积小于 K 的子数组】

题目 给定一个正整数数组 nums和整数 k &#xff0c;请找出该数组内乘积小于 k 的连续的子数组的个数。 示例 1: 输入: nums [10,5,2,6], k 100输出: 8解释: 8 个乘积小于 100 的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。 需要注意的是 [10,5,2]…

代码-【5 二叉树非递归后序遍历,找指定结点的父节点】

二叉树T按二叉链表存储&#xff0c;求指定结点q的父节点&#xff1a;

通过一次线上问题,讲下Ribbon重试机制

前言 前段时间&#xff0c;产品经理在线上验证产品功能的时候&#xff0c;发现某个功能不符合需求预期&#xff0c;后来测试验证发现是服务端的一个接口大概率偶现超时&#xff0c;前端做了兜底处理&#xff0c;所以对线上用户么有太大影响。 问题排查过程 由于服务端的接口…

【暑期每日一练】 day8

目录 选择题 &#xff08;1&#xff09; 解析&#xff1a; &#xff08;2&#xff09; 解析&#xff1a; &#xff08;3&#xff09; 解析&#xff1a; &#xff08;4&#xff09; 解析&#xff1a; &#xff08;5&#xff09; 解析&#xff1a; 编程题 题一 描述…

简单聊聊创新与创造力

文章目录 前言一、大脑运行的两种方式1、聚焦模式2、发散模式3、影响想法的因素a、背景知识b、兴趣c、天赋 4、思维固化 二、想法的不可靠1、对想法进行验证2、颠覆性创新&#xff0c;挤牙膏式创新3、为什么模仿这么多 三、更多更多的idea1、个人的方面a、积累不同的背景知识b、…

怎么在线修改图片?分享一个图片修改工具

无论是在个人或商业领域&#xff0c;我们都需要使用高质量的图片来传达信息或提高品牌形象。大尺寸的图片也会占据大量的存储空间和带宽&#xff0c;影响网站的加载速度和用户体验。因此&#xff0c;我们需要一种高效的工具来解决这个问题。今天向大家介绍一款非常实用的图片处…

(学习笔记-内存管理)内存分段、分页、管理与布局

内存分段 程序是由若干个逻辑分段组成的&#xff0c;比如可由代码分段、数据分段、栈段、堆段组成。不同的段是有不同的属性的&#xff0c;所以就用分段的形式把这些分段分离出来。 分段机制下&#xff0c;虚拟地址和物理地址是如何映射的&#xff1f; 分段机制下的虚拟地址由…

JetBrains 为测试自动化打造的强大 IDE-Aqua

QA 和测试工程对现代软件开发必不可少。 在 JetBrains&#xff0c;我们相信使用正确的工具对每项工作都很重要。 对我们来说&#xff0c;为自动化测试开发创建单独的工具是自然而然的事&#xff0c;因为这使我们能够满足多角色软件开发团队的需求。 我们很高兴能够推出 JetBra…

【Vscode】远程内存占用大

查看远程服务器上的扩展 依次删除&#xff0c;重新连接后观察内存占用 此扩展占用较高&#xff0c;约2G&#xff08;前后端项目&#xff0c;依赖较多导致&#xff09;

JS前端读取本地上传的File文件对象内容(包括Base64、text、JSON、Blob、ArrayBuffer等类型文件)

读取base64图片File file2Base64Image(file, cb) {const reader new FileReader();reader.readAsDataURL(file);reader.onload function (e) {cb && cb(e.target.result);//即为base64结果}; }, 读取text、JSON文件File readText(file, { onloadend } {}) {const re…

一个写了3年半flutter的小伙,突然写了2个月uniapp的感悟!

前言 因为某些原因&#xff0c;在过去的三年半时间&#xff0c;我除了flutter之外&#xff0c;很少接触其他的框架&#xff0c;期间除了学习了Android&#xff08;主要是Kotlin、jetpack&#xff09;、GoLang Gin之外基本上很少接触其他的框架。而在最近的两个月&#xff0c;突…

如何基于 Apache Doris 构建新一代日志分析平台

作者&#xff1a;肖康&#xff0c;SelectDB 技术 副总裁 、Apache Doris Committer 日志数据是企业大数据体系中重要的组成部分之一&#xff0c;这些数据记录了网络设备、操作系统以及应用程序的详细历史行为&#xff0c;蕴含了丰富的信息价值&#xff0c;在可观测性、网络安全…

项目篇:Echo论坛系统项目

一、登录注册模块 1、注册功能 1.1、注册流程图 1.2、注册代码 /*** 用户注册* param user* return Map<String, Object> 返回错误提示消息&#xff0c;如果返回的 map 为空&#xff0c;则说明注册成功*/public Map<String, Object> register(User user) {Map&l…

YOLOv8实现K折交叉验证教程:解决数据集样本稀少和类别不平衡的难题

本篇博文为大家讲解 YOLOv8 实现 k折交叉验证的流程,包含代码使用和讲解。 K折交叉验证 概念 K折交叉验证 (K-fold cross-validation) 是一种常用于评估机器学习模型性能的技术。 它可以更充分地利用有限的数据集,减少由于数据划分不当而引起的偏差,提高模型的泛化能力。…

计算机里基本硬件的组成以及硬件协同

文章目录 冯诺依曼体系输入设备输出设备存储器运算器控制器协同工作的流程 冯诺依曼体系 世界上第一台通用计算机&#xff0c;ENIAC&#xff0c;于1946年诞生于美国一所大学。 ENIAC研发的前期&#xff0c;需要工作人员根据提前设计好的指令手动接线&#xff0c;以这种方式输入…

卸载大脑,相信DFS

切莫相信动规&#xff0c;吾将为您指明前进之路 印子 比赛时&#xff0c;你是否有这样的经历&#xff1a;不敢用for暴搜&#xff0c;又不会用数学公式推理&#xff1b;焦急地在纸上打草&#xff0c;却没有优化思路&#xff1b;明明比赛前一天晚上背了那么多模板却脑子一片空白…

Modbus tcp转ETHERCAT网关modbus tcp/ip协议

捷米JM-ECT-TCP网关能够连接到Modbus tcp总线和ETHERCAT总线中&#xff0c;实现两种不同协议设备之间的通讯。这个网关能够大大提高工业生产的效率和生产效益&#xff0c;让生产变得更加智能化。捷米JM-ECT-TCP 是自主研发的一款 ETHERCAT 从站功能的通讯网关。该产品主要功能是…

《Deep Leakage from Gradients》

Deep Leakage from Gradients 摘要 现在的分布式机器学习&#xff0c;或联邦学习中最常用的一种方法就是交换梯度&#xff0c;长期以来人们都认为交换梯度的安全的&#xff0c;但是本文提出从公开共享的梯度中获得私有训练数据是可能的。文章将这种泄漏命名为Deep leak from …