Spring框架----AOP全集

一:AOP概念的引入

首先我们来看一下登录的原理
在这里插入图片描述
如上图所示这是一个基本的登录原理图,但是如果我们想要在这个登录之上添加一些新的功能,比如权限校验
那么我们能想到的就有两种方法:
①:通过对源代码的修改实现
②:不通过修改源代码方式添加新的功能 (AOP)
在这里插入图片描述

二:AOP相关的概念

1. AOP的概述

什么是AOP的技术?
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程
AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构。
AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范。
通过预编译方式或者运行期动态代理实现程序功能的统一维护的一种技术
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码(事务管理、安全检查、缓存)
为什么要学习AOP,可以在不修改源代码的前提下,对程序进行增强!!

2. AOP的优势

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

  1. 减少重复的代码
  2. 提供开发的效率
  3. 维护方便

3. AOP的底层原理

JDK的动态代理技术
1、为接口创建代理类的字节码文件
2、使用ClassLoader将字节码文件加载到JVM
3、创建代理类实例对象,执行对象的目标方法
cglib代理技术
为类生成代理对象,被代理类有没有接口都无所谓,底层是生成子类,继承被代理类。
在这里插入图片描述

三:Spring的AOP技术-配置文件方式

1. AOP相关的术语

Joinpoint(连接点) 类里面有哪些方法可以增强这些方法称为连接点
Pointcut(切入点) – 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
Advice(通知/增强)-- 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Aspect(切面)-- 是 切入点+通知 的结合,以后咱们自己来编写和配置的
在这里插入图片描述

2. 基本准备工作

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

3. AOP配置文件方式的入门

创建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>

创建被增强的类

// 被增强的类
public class User {
    //连接点/切入点
    public void add(){
        System.out.println("add......");
    }
    public void update(){
        System.out.println("update......");
    }
}

将目标类配置到Spring中

<bean id="user" class="com.aopImpl.User"></bean>

定义切面类

public class UserProxy {
    //增强/通知  ---》前置通知
    public void before(){
        System.out.println("before.............");
    }
}

在配置文件中定义切面类

<bean id="userProxy" class="com.aopImpl.UserProxy"></bean>

在配置文件中完成aop的配置

<!--配置切面-->
<aop:config>
    <!--配置切面 = 切入点 + 通知组成-->
    <aop:aspect ref="userProxy">
        <!--前置通知:UserServiceImpl的save方法执行前,会增强-->
        <!--pointcut:后边是切入点表达式,作用是知道对对面的那个方法进行增强-->
        <aop:before method="before" pointcut="execution(public void com.aopImpl.User.add())"/>
    </aop:aspect>
</aop:config>

完成测试

public class DemoTest {
    @Test
    public void aopTest1(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) applicationContext.getBean("user");
        user.add();
    }
}

4. 切入点的表达式

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

execution([修饰符] [返回值类型] [类全路径] [方法名 ( [参数] )])
修饰符可以省略不写,不是必须要出现的。
返回值类型是不能省略不写的,根据你的方法来编写返回值,可以使用 * 代替。

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

例如:com.qcby.demo3.BookDaoImpl.save()
首先包名,类名,方法名是不能省略不写的,但是可以使用 * 代替
中间的包名可以使用 * 号代替
类名也可以使用 * 号代替,也有类似的写法:*DaoImpl
方法也可以使用 * 号代替
参数如果是一个参数可以使用 * 号代替,如果想代表任意参数使用 ..


比较通用的表达式:execution(* com.qcby.*.ServiceImpl.save(..))
举例2com.qcby.demo3.BookDaoImpl当中所有的方法进行增强
execution(* com.qcby.*.ServiceImpl.*(..))
举例3:com.qcby.demo3包当中所有的方法进行增强
execution(* com.qcby.*.*.*(..))
<!--配置切面-->
<aop:config>
    <!--配置切面 = 切入点 + 通知组成-->
    <aop:aspect ref="userProxy">
        <!--切入点的表达式
        execution() 固定的写法
        public 是可以省略不写的
        方法的返回值 int String 通用的写法,可以编写 * 不能省略不写的
        包名+类名 不能省略不写的,编写 * com.*
        方法名称 add() 可以写 *
        参数列表 (..) 表示任意类型和个数的参数
        比较通用的表达式:execution(* com.*.User.add(..))-->
        <aop:before method="before" pointcut="execution(* com.*.User.add(..))"/>
    </aop:aspect>
</aop:config>

5. AOP的通知类型

①: 前置通知 目标方法执行前,进行增强。

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

② 环绕通知 目标方法执行前后,都可以进行增强。目标对象的方法需要手动执行。

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

xml配置

<aop:around method="around" pointcut="execution(* com.*.User.add(..))"/>

③. 最终通知 目标方法执行成功或者失败,进行增强。

// 最终通知
public void after() {
    System.out.println("after.............");
}

xml配置

<aop:after method="after" pointcut="execution(* com.*.User.add(..))"/>

④. 后置通知 目标方法执行成功后,进行增强。

//后置通知
public void afterReturning() {
    System.out.println("afterReturning.............");
}

xml配置

<aop:after-returning method="afterReturning" pointcut="execution(public void com.aopImpl.User.add())"/>

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

//异常通知
public void afterThrowing() {

    System.out.println("afterThrowing.............");
}

需要改动一下切点

//连接点/切入点
public void add(){
    int a = 10 / 0;
    System.out.println("add......");
}

xml配置

<aop:after-throwing method="afterThrowing" pointcut="execution(public void com.aopImpl.User.add())"/>

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

1. AOP注解方式入门程序

创建maven工程,导入坐标。编写接口,完成IOC的操作。步骤略。
编写切面类
给切面类添加注解 @Aspect,编写增强的方法,使用通知类型注解声明
①.配置xml扫描注解

<?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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

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

②.配置注解

@Component
public class User {
    //连接点/切入点
    public void add(){
        System.out.println("add......");
    }
}

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

@Component
@Aspect  //生成代理对象
public class UserProxy {

}

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

<?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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--开启注解扫描-->
    <context:component-scan base-package="com.aopImpl"></context:component-scan>
    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

④.通知类型注解
@Before – 前置通知
@AfterReturing – 后置通知
@Around – 环绕通知(目标对象方法默认不执行的,需要手动执行)
@After – 最终通知
@AfterThrowing – 异常抛出通知

@Component
@Aspect  //生成代理对象
public class UserProxy {
    //增强/通知  ---》前置通知
    @Before(value = "execution(* com.*.User.add(..))")
    public void before(){
        System.out.println("before.............");

    }

    // 环绕通知
    @Around(value = "execution(* com.*.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("before.............");
        //  执行被增强的方法
        proceedingJoinPoint.proceed();
        System.out.println("after.............");
    }

    // 最终通知
    @After(value = "execution(* com.*.User.add(..))")
    public void after() {

        System.out.println("after.............");
    }

    //异常通知
    @AfterThrowing(value = "execution(* com.*.User.add(..))")
    public void afterThrowing() {

        System.out.println("afterThrowing.............");
    }

    //后置通知
    @AfterReturning(value = "execution(* com.*.User.add(..))")
    public void afterReturning() {

        System.out.println("afterReturning.............");
    }
}

⑤.测试类

@Test
public void aopTest1(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    user.add();
}

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

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

相关文章

Android实现点击获取验证码60秒后重新获取功能

本文实例为大家分享了Android实现点击获取验证码60秒后重新获取的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 上代码 /*** Created by Xia_焱 on 2017/5/7.*/public class CountDownTimerUtils extends CountDownTimer {private TextView mTextView;/*** param…

Requests教程-17-请求代理设置

上一小节我们学习了requests解决乱码的方法&#xff0c;本小节我们讲解一下requests设置代理的方法。 代理基本原理 代理实际上指的就是代理服务器&#xff0c; 英文叫作proxy server &#xff0c;它的功能是代理网络用户去取得网络信息。形象地说&#xff0c;它是网络信息的中…

Android Studio入门——页面跳转

1.工程目录 2.MainActivity package com.example.demo01;import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCo…

前端开发小技巧 - 【Vue3 + TS】 - 在 TS + Vue3 中使用 Pinia,实现 Pinia 的持久化,优化Pinia(仓库统一管理)

前言 ts 中使用 pinia 和 Vue3 基本一致&#xff0c;唯一的不同点在于&#xff0c;需要根据接口文档给 state 标注类型&#xff0c;也要给 actions 标注类型&#xff1b;以下都是 组合式API 的写法&#xff0c;选项式API 的写法大家可以去官网看看&#xff1b; Pinia&#xff…

Text-to-SQL 工具Vanna进阶|数据库对话机器人的多轮对话

跟数据库对话机器人对话,我可不止一个问题。 可能基于第一句问话,还有第二句、第三句问话。。。第N句对话。所以本文测试了多轮对话功能。 单轮对话的环境搭建参考博客 Text-to-SQL 工具Vanna + MySQL本地部署 | 数据库对话机器人 我的数据是这样 1. 基础配置 import vann…

深入解析Java中锁机制以及底层原理

一、概述 1.1 背景 概念&#xff1a;锁是多线程编程中的机制&#xff0c;用于控制对共享资源的访问。可以防止多个线程同时修改或读取共享资源&#xff0c;从而保证线程安全。 作用&#xff1a;锁用于实现线程间的互斥和协调&#xff0c;确保在多线程环境下对共享资源的访问顺…

前端性能优化——javascript

优化处理&#xff1a; 讲javascript脚本文件放到body标记的后面 减少页面当中所包含的script标记的数量 课堂练习&#xff1a; 脚本优化处理 使用原生JavaScript完成操作过程。 document.querySelector document.querySelectorAll classList以及类的操作API Element.class…

LLM之RAG实战(二十九)| 探索RAG PDF解析

对于RAG来说&#xff0c;从文档中提取信息是一种不可避免的场景&#xff0c;确保从源文件中提取出有效的内容对于提高最终输出的质量至关重要。 文件解析过程在RAG中的位置如图1所示&#xff1a; 在实际工作中&#xff0c;非结构化数据比结构化数据丰富得多。如果这些海量数据无…

记录西门子:SCL设置不同顺序

一台搅拌的设备&#xff0c;需要控制三种料的进料顺序和进料重量&#xff0c;顺序和重量可以随便设定&#xff0c;也可以是几十种料。触摸屏上面有A、B、C三种液体原料&#xff0c;需要设定三种液体原料重量&#xff0c;并设定序号。 假设如下面所示设定&#xff1a;那将先打开…

java数据结构与算法刷题-----LeetCode90. 子集 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 解题思路:时间复杂度O( n 2 ∗ n n^2*n n2∗n),空间复杂度O(n) 7…

开箱机自动化装箱技术:原理、应用与未来趋势

在物流、电商等行业中&#xff0c;开箱机作为自动化装箱技术的核心设备&#xff0c;正逐渐改变着传统的包装方式&#xff0c;为企业带来了效率和成本的双重优化。星派将从开箱机的原理出发&#xff0c;详细解析其应用领域&#xff0c;并展望未来的发展趋势。 一、开箱机的工作原…

《高效便捷,探索快递柜系统架构的智慧之路》

随着电商业务的蓬勃发展&#xff0c;快递柜系统作为一种高效、便捷的最后一公里配送解决方案&#xff0c;正在受到越来越多企业和消费者的青睐。本篇博客将深入探讨快递柜系统的架构设计理念、优势和实践&#xff0c;帮助读者了解如何构建智能化的快递柜系统&#xff0c;提升物…

【UE5】非持枪状态蹲姿移动的动画混合空间

项目资源文末百度网盘自取 在BlendSpace文件夹中单击右键选择动画(Animation)中的混合空间(Blend Space) &#xff0c;选择SK_Female_Skeleton&#xff0c;命名为BS_NormalCrouch 打开BS_NormalCrouch 水平轴表示角色的方向&#xff0c;命名为Direction&#xff0c;方向的最…

教师如何搭建学生查询考试分数的平台?

随着信息技术的快速发展&#xff0c;搭建一个学生查询考试分数的平台已经成为现代教育管理的重要组成部分。这样的平台不仅可以提高成绩管理的效率&#xff0c;还能为学生提供便捷、及时的成绩查询服务。那么&#xff0c;作为教师&#xff0c;我们应该如何搭建这样一个平台呢&a…

低代码开发平台,快速搭建开源MES系统

MS低代码云MES作为一家专注于提供生产制造数字化方案的服务商&#xff0c;“以客户为中心”、以“数据驱动、智能化、互联化”为企业的核心标签&#xff0c;以低代码平台为切入点&#xff0c;帮助企业构建以人为本的未来供应链生态系统&#xff0c;实现制造企业的智能化转型。 …

Simple Admin:基于Go Zero的大型项目分布式微服务后端管理系统

Simple Admin 是一个开箱即用的分布式微服务后端管理系统&#xff0c;基于go-zero开发&#xff0c;为开发中大型后台提供了丰富的功能&#xff0c;支持三端代码生成。 官方自带多种扩展&#xff0c;助力中小企业快速上云&#xff0c;快速迭代。适合用于微服务学习和商用&#x…

如何拆解技术瓶颈的难点

以大化小的思路 解决一个一个小问题从而解决最终问题 三段论&#xff1a; 抽象能力 职责领域划分 分层构建解决方案 案例&#xff1a;全局分布式事务的解决方案 抽象能力&#xff1a;全局分布式 是由一个个小的事务组合而成的&#xff0c;其中一个分布式事务出现问题&#xff…

VsCode免密登录

创建本地密匙 按下WinR输入cmd&#xff0c;输入 ssh-keygen -t rsa然后连续回车直到结束 找到Your public key has been saved in C:\Users\Administrator/.ssh/id_rsa.pub&#xff0c;每个人都不一样找到密匙所在地 打开id_rsa.pub这个文件&#xff0c;可以用记事本打开&am…

wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)

文章目录 前言一、使用 stb_image 库加载纹理图片1. 获取 stb_image.h 头文件2. 使用 stb_image.h 中的相关接口加载纹理图片3. 纹理图片——cordeBouee4.jpg二、渲染使用纹理贴图的旋转 3D 立方体1. egl_wayland_texture_cube.c2. Matrix.h 和 Matrix.c3. xdg-shell-client-pr…

Nacos 集群搭建

1 . 集群结构图 : 其中包括3个nacos结点&#xff0c;然后一个负载均衡器代理3个Nacos。这里负载均衡器可以使用nginx ; 我们计划的集群结构 : 三个nacos结点的地址 : 节点ipportnacos1192.168.150.18845nacos2192.168.150.18846nacos3192.168.150.18847 2 . 搭建集群 搭…
最新文章