【Spring】Spring框架之-AOP

目录

1. AOP的引入

2. AOP相关的概念

2.1 AOP概述

2.2 AOP的优势

2.3. AOP的底层原理--目前先不具体阐述,后面讲

 3. Spring的AOP技术-配置文件方式

3.1 AOP相关的术语

3.2 基本准备工作

3.3 AOP配置文件方式的入门

3.4 切入点的表达式

 3.5 AOP的通知类型

1. 前置通知

2. 环绕通知

3. 最终通知

4.  后置通知

 4. Spring的AOP技术-注解方式

4.1. AOP注解方式入门程序

1. 配置xml扫描注解

2. 配置注解 

3. 配置文件中开启自动代理

4. 通知类型注解


1. AOP的引入

首先我们来看一下登录的原理

        如上图所示这是一个基本的登录原理图,但是如果我们想要在这个登录之上添加一些新的功能,比如权限校验

那么我们能想到的就有两种方法:

①:通过对源代码的修改实现 

②:不通过修改源代码方式添加新的功能 (AOP)

 


2. AOP相关的概念

2.1 AOP概述

什么是AOP的技术?

        在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程

        AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构。

        AOP最早由AOP联盟的组织提出的,制定了一套规范.  Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范。

        通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术。

        AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

        利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率.

        AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(事务管理、安全检查、缓存)

为什么要学习AOP?

        可以在不修改源代码的前提下,对程序进行增强!!-->也就是增加功能

2.2 AOP的优势

运行期间,不修改源代码的情况下对已有的方法进行增强

优势:

        1. 减少重复的代码

        2. 提供开发的效率

        3. 维护方便

2.3. AOP的底层原理--目前先不具体阐述,后面讲

JDK的动态代理技术

        1、为接口创建代理类的字节码文件

        2、使用ClassLoader将字节码文件加载到JVM

        3、创建代理类实例对象,执行对象的目标方法

cglib代理技术

        为类生成代理对象,被代理类有没有接口都无所谓,底层是生成子类,继承被代理类。


 3. Spring的AOP技术-配置文件方式

3.1 AOP相关的术语

        Joinpoint(连接点) 类里面有哪些方法可以增强这些方法称为连接点。

        Pointcut(切入点) -- 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义。

        Advice(通知/增强)-- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)。

        Aspect(切面)-- 是 切入点+通知 的结合,以后咱们自己来编写和配置的。

 

        成熟的不能作为连接点,但是成熟的没见过,就是都能作为连接点。

        增加功能的代码就是增强。

        try-catch-finally,finally永远都会执行。


3.2 基本准备工作

        AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法,AspectJ实际上是对AOP编程思想的一个实践。

3.3 AOP配置文件方式的入门

$1. 创建maven项目,坐标依赖

<dependencies>
    <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>
</dependencies>

 注意!!

        我这里Maven配置时 aspectj 是空项目,就是之前没有下载,因此一直报错。

        如果你也一直报错,右键鼠标,点击Maven,下载资源即可解决!!

 $2. 创建被增强的类

public class Cat {


    public void add(int nums){
        System.out.println("添加了"+nums);
    }

    public void delete(int nums){
        System.out.println("删除了"+nums);
    }
    public void update(){
        System.out.println("进行了修改");
    }

    public void login(String username,String password){
        System.out.println("进行数据库对比");
    }


}

         我们在登录时增加权限验证。

$3. 将目标类配置到Spring中。

<bean name="cat" class="com.qcby.service.Cat"/>

$4. 定义切面类

public class 权限 {
    public void 验证(){
        System.out.println("进行权限验证");
    }
}

$5. 在配置文件中定义切面类

<bean name="qx" class="com.qcby.service.权限"/>

$6. 在配置文件中完成AOP的配置

<!--pointcut:后边是切入点表达式,作用是知道对对面的那个方法进行增强-->

<aop:config>
        <!--配置切面 = 切入点 + 通知组成-->
        <aop:aspect ref="qx">
            <aop:before method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>
            <!--after:最终通知finally(无论成功或失败都会执行)-->
<!--            <aop:after method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>-->
<!--            <aop:after-returning method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>-->
<!--            <aop:after-throwing method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>-->

<!--                <aop:around method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>-->
        </aop:aspect>
    </aop:config>

$7. 测试test

public class Test2 {
    @Test
    public void test(){
        ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("Spring.xml");
        Cat cat=(Cat) ac.getBean("cat");
        cat.login("小猫","1245");
    }
}


3.4 切入点的表达式

再配置切入点的时候,需要定义表达式,具体展开如下:

        切入点表达式的格式如下:

                execution([修饰符] [返回值类型] [类全路径] [方法名 ( [参数] )])

 其中,

        修饰符可以省略不写,不是必须要出现的。

        返回值类型是不能省略不写的,根据你的方法来编写返回值,可以使用 * 代替。

包名,类名,方法名,参数的规则如下:

例如

        com.qcby.demo3.BookDaoImpl.save()

1. 首先包名,类名,方法名是不能省略不写的,但是可以使用 * 代替

2. 中间的包名可以使用 * 号代替

3. 类名也可以使用 * 号代替,也有类似的写法:*DaoImpl

4. 方法也可以使用 * 号代替

5. 参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..

比较通用的表达式

                execution(* com.qcby.*.ServiceImpl.save(..))

举例2

        com.qcby.demo3.BookDaoImpl当中所有的方法进行增强

                        execution(* com.qcby.*.ServiceImpl.*(..))

举例3

        com.qcby.demo3包当中所有的方法进行增强

                        execution(* com.qcby.*.*.*(..))


 3.5 AOP的通知类型

1. 前置通知

目标方法执行前,进行增强。

        如上配置案例就是前置通知。

2. 环绕通知

目标方法执行前后,都可以进行增强。

目标对象的方法需要手动执行。

// 环绕通知
public void 验证(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    System.out.println("before.............");
    //  执行被增强的方法
    proceedingJoinPoint.proceed();
    
    System.out.println("after.............");
}

xml配置

<aop:around method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>

3. 最终通知

目标方法执行成功或者失败,进行增强。

public class Cat {


    public void add(int nums){
        System.out.println("添加了"+nums);
    }

    public void delete(int nums){
        System.out.println("删除了"+nums);
    }
    public void update(){
        System.out.println("进行了修改");
    }

    public void login(String username,String password){
        int a=10/0;
        System.out.println("进行数据库对比");
    }


}
public class 权限 {
    public void 验证(){
        System.out.println("进行权限验证");
    }
}

xml配置

<aop:after method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>

测试:         

        切入点有错误还是进行了增强。 

4.  后置通知

目标方法执行成功后,进行增强。

目标文件配置

public void login(String username,String password){
        int a=10/0;
        System.out.println("进行数据库对比");
    }

xml配置

<aop:after-returning method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>

目标方法有错误,不进行增强。 

改正后: 

 public void login(String username,String password){
//        int a=10/0;
        System.out.println("进行数据库对比");
    }

可以进行增强。

5. 异常通知

目标方法执行失败后,进行增强。(发生异常的时候才会执行,否则不执行)

目标文件

public void login(String username,String password){
        int a=10/0;
        System.out.println("进行数据库对比");
    }

xml配置: 

<aop:after-throwing method="验证" pointcut="execution(public void com.qcby.service.Cat.login(..))"/>

测试

若目标文件改正确之后,

不进行增强


 4. Spring的AOP技术-注解方式

4.1. AOP注解方式入门程序

创建maven工程,导入坐标。编写接口,完成IOC的操作。步骤略。

编写切面类

给切面类添加注解 @Aspect,编写增强的方法,使用通知类型注解声明。

1. 配置xml扫描注解

<!--开启注解扫描-->
    <context:component-scan base-package="com.qcby"></context:component-scan>

2. 配置注解 

给切面类添加注解 @Aspect,编写增强的方法,使用通知类型注解声明

@Component
@Aspect  //生成代理对象
public class 权限 {
    public void 验证(){
        System.out.println("进行权限验证");
    }
}
@Component
public class Cat {


    public void add(int nums){
        System.out.println("添加了"+nums);
    }

    public void delete(int nums){
        System.out.println("删除了"+nums);
    }
    public void update(){
        System.out.println("进行了修改");
    }

    public void login(String username,String password){
//        int a=10/0;
        System.out.println("进行数据库对比");
    }


}

3. 配置文件中开启自动代理

<!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

4. 通知类型注解

@Before -- 前置通知

@AfterReturing -- 后置通知

@Around -- 环绕通知(目标对象方法默认不执行的,需要手动执行)

@After -- 最终通知

@AfterThrowing -- 异常抛出通知

 @Before -- 前置通知

@Before(value = "execution(public void com.qcby.service.Cat.login(..))")
    public void before(){
        System.out.println("before.............");

    }

 @AfterReturing -- 后置通知

@AfterReturning(value = "execution(public void com.qcby.service.Cat.login(..))")
    public void 验证(){
        System.out.println("before.............");

    }

@Around -- 环绕通知(目标对象方法默认不执行的,需要手动执行) 

@Around(value = "execution(public void com.qcby.service.Cat.login(..))")
    public void before(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        System.out.println("before.............");
        //  执行被增强的方法
        proceedingJoinPoint.proceed();
        System.out.println("after.............");
    }

@After -- 最终通知 

@After(value = "execution(public void com.qcby.service.Cat.login(..))")
    public void 验证(){
        System.out.println("before.............");

    }

@AfterThrowing -- 异常抛出通知 

@AfterThrowing(value = "execution(public void com.qcby.service.Cat.login(..))")
    public void 验证(){
        System.out.println("before.............");

    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我的2024年度总结

称着这个周末&#xff0c;写一篇2024年度总结&#xff0c;主要记录我过去一年的成长经历以及自己的一些收获。 过去一年的经历&#xff0c;可谓刻骨铭心&#xff0c;一个是24考研惨败&#xff0c;一个是毕设的准备&#xff0c;一个是省考的陪考&#xff0c;一个是找工作的焦虑…

Java 中的字符串

目录 Java 中的字符串字符串的创建字符串的比较字符串的拼接如何定义一个空的字符串 Java 中的字符串 字符串的创建 在 Java 中&#xff0c;可以通过以下几种方式创建字符串&#xff1a; 1.使用字符串字面量&#xff1a; String str "Hello, World!";2.使用 new…

数说故事聚焦“卖车”场景,推出AI汽车销售转化解决方案

没错&#xff0c;“卖车”我们也在行&#xff0c;为某车企“保住”了新车上市的订单。 深耕汽车行业多年&#xff0c;该车企10月份刚发布一款新能源车&#xff0c;其前期已经拥有了大量的保有客户和线上多渠道获取的潜在客户&#xff0c;然而&#xff0c;仍面临两大难题&#x…

javaEE-多线程编程-3

目录 java 常见的包 : 回调函数: 什么是线程: 第一个线程: 验证多线程执行: 内核: 调用sleep()方法: 执行结果分析: 线程创建的几种方式: 1.继承Thread类,重写run()方法. 2.实现Runnable接口,重写run()方法. 3.继承Thread类,重写run()方法.但使用匿名内部类 4.实现…

FFmpeg 框架简介和文件解复用

文章目录 ffmpeg框架简介libavformat库libavcodec库libavdevice库 复用&#xff08;muxers&#xff09;和解复用&#xff08;demuxers&#xff09;容器格式FLVScript Tag Data结构&#xff08;脚本类型、帧类型&#xff09;Audio Tag Data结构&#xff08;音频Tag&#xff09;V…

芯片级IO (Pad) Ring IP Checklist

SoC top顶层数字后端实现都会涉及到IO Ring &#xff08;PAD Ring&#xff09;的设计。这里面包括VDD IO,VDDIO IO, Signal IO, Corner IO&#xff0c;Filler IO&#xff0c;IO power cut cell等等。 数字后端零基础入门系列 | Innovus零基础LAB学习Day2 数字IC后端实现TOP F…

圣诞快乐(h5 css js(圣诞树))

一&#xff0c;整体设计思路 圣诞树h5&#xff08;简易&#xff09; 1.页面布局与样式&#xff1a; 页面使用了全屏的黑色背景&#xff0c;中央显示圣诞树&#xff0c;树形由三层绿色的三角形组成&#xff0c;每一层的大小逐渐变小。树干是一个棕色的矩形&#xff0c;位于三角…

Linux应用开发————mysql数据库表

mysql数据库表操作 查看表的结构 mysql> desc / describe 表名; 或者&#xff1a; mysql> show create table 表名; 常见数据库引擎&#xff1a; innodb, myISAM... 删除表 mysql> drop tabl…

移动网络(2,3,4,5G)设备TCP通讯调试方法

背景&#xff1a; 当设备是移动网络设备连接云平台的时候&#xff0c;如果服务器没有收到网络数据&#xff0c;移动物联设备发送不知道有没有有丢失数据的时候&#xff0c;需要一个抓取设备出来的数据和服务器下发的数据的方法。 1.服务器系统是很成熟的&#xff0c;一般是linu…

Unity中的委托和事件(UnityAction、UnityEvent)

委托和事件 &#x1f392;什么是委托&#xff0c;委托的关键字是Delegate&#xff0c;委托是一种函数的容器&#xff0c;运行将函数做为变量来进行传递 通过Delegate关键字我们声明了一个无参无返回的委托&#xff0c;通过这个委托我们可以存储无参无返回的函数 public deleg…

基于SpringBoot的“交流互动系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“交流互动系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 系统功能图 管理员登录界面图 个人信息界面图 个人…

LeetCode hot100-93

https://leetcode.cn/problems/longest-palindromic-substring/description/?envTypestudy-plan-v2&envIdtop-100-liked 5. 最长回文子串 给你一个字符串 s&#xff0c;找到 s 中最长的回文子串。状态定义 我们用一个二维数组 dp[i][j] 表示子串 s[i…j] 是否是回文&…

C语言入门指南:从零开始的编程之路

记得我刚开始接触编程时,也像很多初学者一样充满疑惑。编程看起来很神奇,但要如何开始呢?经过多年编程经验的积累,今天和大家分享如何入门C语言编程。 C语言诞生于1972年,由Dennis Ritchie在贝尔实验室开发。它的出现彻底改变了计算机编程的历史。虽然现在有很多更新的编程语…

详解Redis的String类型及相关命令

目录 SET GET MGET MSET SETNX SET和SETNX和SETXX对比 INCR INCRBY DECR DECRBY INCRBYFLOAT APPEND GETRANGE SETRANGE STRLEN 内部编码 SET 将 string 类型的 value 设置到 key 中。如果 key 之前存在&#xff0c;则覆盖&#xff0c;⽆论原来的数据类型是什么…

SpringBoot使用 AOP 实现自定义日志记录并保存在Mysql

本文主要介绍在 Spring Boot 中使用 AOP 实现自定义日志记录并保存在 Mysql 的方法。先阐述记录日志的重要性及传统方式的弊端&#xff0c;提出新方式&#xff0c;即通过创建自定义注解、切面类等&#xff0c;将重要日志存到数据库&#xff0c;还给出了创建日志表、注解类、切面…

对golang的io型进程进行off-cpu分析

背景&#xff1a; 对于不能占满所有cpu核数的进程&#xff0c;进行on-cpu的分析是没有意义的&#xff0c;因为可能程序大部分时间都处在阻塞状态。 实验例子程序&#xff1a; 以centos8和golang1.23.3为例&#xff0c;测试下面的程序&#xff1a; pprof_netio.go package m…

CTF入门:以Hackademic-RTB1靶场为例初识夺旗

一、网络扫描 靶机ip地址为192.168.12.24 使用nmap工具进行端口扫描 nmap -sT 192.168.12.24 二、信息收集 1、80端口探索 靶机开放了80和22端口&#xff0c;使用浏览器访问靶机的80端口&#xff0c;界面如下&#xff1a; 点击target发现有跳转&#xff0c;并且url发生相应变…

腾讯云智能结构化OCR:以多模态大模型技术为核心,推动跨行业高效精准的文档处理与数据提取新时代

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大三学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

SD ComfyUI工作流 根据图像生成线稿草图

文章目录 线稿草图生成SD模型Node节点工作流程工作流下载效果展示线稿草图生成 该工作流的设计目标是将输入的图像转换为高质量的线稿风格输出。其主要流程基于 Stable Diffusion 技术,结合文本和图像条件,精确生成符合预期的线条艺术图像。工作流的核心是通过模型的条件设置…

Zabbix6.0升级为6.4

为了体验一些新的功能&#xff0c;比如 Webhook 和问题抑制等&#xff0c;升级个小版本。 一、环境信息 1. 版本要求 一定要事先查看官方文档&#xff0c;确认组件要求的版本&#xff0c;否则版本过高或者过低都会出现问题。 2. 升级前后信息 环境升级前升级后操作系统CentOS…