当前位置: 首页 > news >正文

Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

目录

    • AOP
      • 概念
      • AOP底层原理
      • AOP(JDK动态代理)
        • 使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象
        • **编写** **JDK** 动态代理代码
      • AOP(术语)
      • AOP操作(准备工作)
      • **AOP** **操作(**AspectJ注解)
      • **AOP** **操作(**AspectJ **配置文件)**

开篇:
欢迎再次来到 Spring 5 学习系列!在这个博客中,我们将深入研究 Spring 框架的AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式)。

AOP

概念

  • 什么是AOP

(1)面向切面编程(方面),利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得

业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

(2)通俗描述:不通过修改源代码方式,在主干功能里面添加新功能

(3)使用登录例子说明 AOP

在这里插入图片描述

AOP底层原理

  1. AOP 底层使用动态代理
  • 两种情况:

    • 第一种 有接口情况,使用 JDK 动态代理

      • 创建接口实现类代理对象,增强类的方法

      在这里插入图片描述

    • **第二种 **没有接口情况,使用 CGLIB 动态代理

      • 创建子类的代理对象,增强类的方法

      在这里插入图片描述

AOP(JDK动态代理)

使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象

下面是jdk8官方文档

compact1, compact2, compact3
java.lang.reflect
Class Proxy
java.lang.Object
java.lang.reflect.Proxystatic Object	newProxyInstance(ClassLoader loader,<?>[] interfaces, InvocationHandler h)
返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
public static Object newProxyInstance(ClassLoader loader,<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
Proxy.newProxyInstance因为与IllegalArgumentException相同的原因而Proxy.getProxyClass 。参数loader - 类加载器来定义代理类interfaces - 代理类实现的接口列表h - 调度方法调用的调用处理函数
结果具有由指定的类加载器定义并实现指定接口的代理类的指定调用处理程序的代理实例
异常IllegalArgumentException - 如果对可能传递给 getProxyClass有任何 getProxyClass被违反
SecurityException -如果安全管理器,S存在任何下列条件得到满足:给定的loader是null ,并且调用者的类加载器不是null ,并且调用s.checkPermission与RuntimePermission("getClassLoader")权限拒绝访问;
对于每个代理接口, intf ,呼叫者的类加载器是不一样的或类加载器的祖先intf和调用s.checkPackageAccess()拒绝访问intf ;
任何给定的代理接口的是非公和呼叫者类是不在同一runtime package作为非公共接口和调用s.checkPermission与ReflectPermission("newProxyInPackage.{package name}")权限拒绝访问。
NullPointerException - 如果 interfaces数组参数或其任何元素是 null ,或者如果调用处理程序 h是 null
  • 调用 newProxyInstance 方法

    • 方法有三个参数:

      第一参数,类加载器

      第二参数,增强方法所在的类,这个类实现的接口,支持多个接口

      第三参数,实现这个接口 InvocationHandler,创建代理对象,写增强的部分

编写 JDK 动态代理代码

(1)创建接口,定义方法

public interface UserDao {public int add(int a,int b);public String update(String id);
}

(2)创建接口实现类,实现方法

public class UserDaoImpl implements UserDao {@Overridepublic int add(int a, int b) {return a+b;}@Overridepublic String update(String id) {return id;}
}

(3)使用 Proxy 类创建接口代理对象

//创建代理对象代码
class UserDaoProxy implements InvocationHandler {//1 把创建的是谁的代理对象,把谁传递过来//有参数构造传递private Object obj;public UserDaoProxy(Object obj) {this.obj = obj;}//增强的逻辑@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//方法之前System.out.println("方法之前行...."+method.getName()+" :传递的参数..."+ Arrays.toString(args));//被增强的方法执行Object res = method.invoke(obj, args);//方法之后System.out.println("方法之后执行...."+obj);return res;}
}
// 测试类这里Proxy.newProxyInstance
public class JDKProxy {public static void main(String[] args) {Class[] interfaces = {UserDao.class};UserDaoImpl userDaoImpl = new UserDaoImpl();UserDao dao = (UserDao)Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDaoImpl));int add = dao.add(2, 3);System.out.println("result:"+add);String update = dao.update("6");System.out.println("result:"+update);}
}

结果

方法之前执行....add :传递的参数...[2, 3]
方法之后执行....com.zhuyh.spring.day0123.aop.dao.impl.UserDaoImpl@2c7b84de
result:5
方法之前执行....update :传递的参数...[6]
方法之后执行....com.zhuyh.spring.day0123.aop.dao.impl.UserDaoImpl@2c7b84de
result:6

AOP(术语)

  1. 连接点

类里面哪些方法可以增强,这些点被称为连接点

  1. 切入点

实际被真正增强的方法

  1. 通知(增强)
  • 实际增强的逻辑部分称为通知(增强)
  • 通知(增强)有多种类型
    • 前置通知
    • 后置通知
    • 环绕通知
    • 异常通知
    • 最终通知
  1. 切面(是动作)

把通知(增强)应用到切入点过程

AOP操作(准备工作)

  1. Spring 框架一般都是基于 AspectJ 实现 AOP 操作

(1)AspectJ 不是 Spring 组成部分,独立 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使

用,进行 AOP 操作

  1. 基于 AspectJ 实现 AOP 操作

(1)基于 xml 配置文件实现

(2)基于注解方式实现(使用)

  1. 在项目工程里面引入 AOP 相关依赖

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 切入点表达式

(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强

(2)语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称] [参数列表])

举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强

execution(* com.atguigu.dao.BookDao.add(…))

举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强

execution(* com.atguigu.dao.BookDao.* (…))举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强

execution(* com.atguigu.dao.. (…))

AOP **操作(**AspectJ注解)

  1. 创建类,在类里面定义方法
public class User {public void add() {System.out.println("add.......");}
}
  1. 创建增强类(编写增强逻辑)
  • 在增强类里面,创建方法,让不同方法代表不同通知类型
//增强的类
public class UserProxy {public void before() {//前置通知System.out.println("before......");}
}
  1. 进行通知的配置
  • 在 spring 配置文件中,开启注解扫描
<?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 basepackage="com.atguigu.spring5.aopanno"></context:component-scan>
  • 使用注解创建 User 和 UserProxy 对象
// 被增强的类
public class User{}
// 增强的类
public class UserProxy{}
  • 在增强类上面添加注解 @Aspect
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {}
  • 在 spring 配置文件中开启生成代理对象
<!-- 开启 Aspect 生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  1. 配置不同类型的通知
  • 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
//增强的类
@Component
@Aspect //生成代理对象
public class UserProxy {//前置通知//@Before 注解表示作为前置通知@Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")public void before() {System.out.println("before.........");}//后置通知(返回通知)@AfterReturning(value = "execution(* 
com.atguigu.spring5.aopanno.User.add(..))")public void afterReturning() {System.out.println("afterReturning.........");}//最终通知@After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")public void after() {System.out.println("after.........");}//异常通知@AfterThrowing(value = "execution(* 
com.atguigu.spring5.aopanno.User.add(..))")public void afterThrowing() {System.out.println("afterThrowing.........");}//环绕通知@Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws 
Throwable {System.out.println("环绕之前.........");//被增强的方法执行proceedingJoinPoint.proceed();System.out.println("环绕之后.........");}
}
  1. 相同的切入点抽取
//相同切入点抽取
@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void pointdemo() {
}
//前置通知
//@Before 注解表示作为前置通知
@Before(value = "pointdemo()")
public void before() {System.out.println("before.........");
}
  1. 有多个增强类多同一个方法进行增强,设置增强类优先级
  • 在增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
@Component
@Aspect
@Order(1)
public class PersonProxy{}
  1. 完全使用注解开发
  • 创建配置类,不需要创建 xml 配置文件
@Configuration
@ComponentScan(basePackages = {"com.atguigu"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}

AOP **操作(**AspectJ 配置文件)

  1. 创建两个类,增强类和被增强类,创建方法

  2. spring 配置文件中创建两个类对象

<!--创建对象-->
<bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
<bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
  1. spring 配置文件中配置切入点
<!--配置 aop 增强-->
<aop:config><!--切入点--><aop:pointcut id="p" expression="execution(* 
com.atguigu.spring5.aopxml.Book.buy(..))"/><!--配置切面--><aop:aspect ref="bookProxy"><!--增强作用在具体的方法上--><aop:before method="before" pointcut-ref="p"/></aop:aspect>
</aop:config>

感谢您阅读 Spring 5 学习系列的第三篇!在这篇文章中,我们探索了Spring5的((AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

下一篇文章即将发布! 在第四篇中,我们将深入研究Spring 5的JdbcTemplate,为您分享我学习的Spring5的收获,请继续关注我的系列。

谢谢您的陪伴! 如果您有任何问题、建议或想要了解的特定主题,请随时在评论中告诉我们。我们期待与您共同探索Spring 5,共同提升我们的Java开发技能!

敬请期待第四篇的发布,我们将很快与您再次见面!

学习视频来源尚硅谷Spring5

相关文章:

Spring5系列学习文章分享---第三篇(AOP概念+原理+动态代理+术语+Aspect+操作案例(注解与配置方式))

目录 AOP概念AOP底层原理AOP(JDK动态代理)使用 JDK 动态代理&#xff0c;使用 Proxy 类里面的方法创建代理对象**编写** **JDK** 动态代理代码 AOP(术语)AOP操作&#xff08;准备工作&#xff09;**AOP** **操作&#xff08;**AspectJ注解)**AOP** **操作&#xff08;**AspectJ…...

BL0942 内置时钟免校准计量芯片 用于智能家居领域 上海贝岭 低成本 使用指南

BL0939是上海贝岭股份有限公司开发的一款用于智能家居领域进行电能测量的专用芯片&#xff0c;支持两路测量&#xff0c;可同时进行计量和漏电故障检测&#xff0c;漏电检测电流可设&#xff0c;响应时间快&#xff0c;具有体积小&#xff0c;外围电路简单&#xff0c;成本低廉…...

【算法专题】动态规划之路径问题

动态规划2.0 动态规划 - - - 路径问题1. 不同路径2. 不同路径Ⅱ3. 珠宝的最高价值4. 下降路径最小和5. 最小路径和6. 地下城游戏 动态规划 - - - 路径问题 1. 不同路径 题目链接 -> Leetcode -62.不同路径 Leetcode -62.不同路径 题目&#xff1a;一个机器人位于一个 m …...

Python range函数

Python中的range()函数是一个强大的工具&#xff0c;用于生成一系列的整数。它在循环、迭代和序列生成等方面都有广泛的应用。本文将深入探讨range()函数的用法&#xff0c;提供详细的示例代码&#xff0c;并讨论其在Python编程中的实际应用。 什么是range()函数&#xff1f; …...

Unity中实现捏脸系统

前言 目前市面上常见的捏脸一般是基于BlendShapes和控制骨骼点坐标两种方案实现的。后者能够控制的精细程度更高&#xff0c;同时使用BlendShapes来控制表情。 控制骨骼点坐标 比如找到控制鼻子的骨骼节点修改localScale缩放&#xff0c;调节鼻子大小。 BlendShapes控制表…...

openssl3.2 - 检查rsa证书和私钥是否匹配(快速手搓一个工具)

文章目录 openssl3.2 - 检查rsa证书和私钥是否匹配(快速手搓一个工具)概述效果笔记编程环境界面控件的设置增加文件拖拽的类RSA证书和key是否匹配的实现在程序中加入环境变量备注备注END openssl3.2 - 检查rsa证书和私钥是否匹配(快速手搓一个工具) 概述 在学习openssl官方的…...

关于网络协议的笔记

简介&#xff1a; 协议&#xff0c; 网络协议的简称&#xff0c;网络协议是通信计算机双方必须共同遵从的一组约定。如怎么样建立连 接、怎么样互相识别等。只有遵守这个约定&#xff0c;计算机之间才能相互通信交流。它的 三要素是&#xff1a;语 法、语义、时序。 为了使数…...

【江科大】STM32:USART串口(理论部分)上

串口 全双工&#xff1a;可以进行同步通信 单端信号&#xff1a;信号线传输的就是单端信号。&#xff08;也就是与地线&#xff08;GND&#xff09;的电势差&#xff09; 缺点&#xff1a;防干扰能力差 原因&#xff1a;当信号从A点传输到B点&#xff0c;理想条件是A&#xff0…...

深入了解Linux中常见的五种文件类型

了解文件类型对于正确理解和管理文件系统非常重要。希望本文能够帮助您更好地了解Linux中常见的文件类型及其在ls -l命令输出中的表示方式。​ 在Linux操作系统中&#xff0c;文件是操作系统中最基本的概念之一。在Linux中&#xff0c;每个文件都有一个特定的类型&#xff0c;这…...

SSM项目集成Spring Security 4.X版本(使用spring-security.xml 配置文件方式)

目录 前言 实战开发&#xff1a; 一、Spring Security整合到SSM项目 1. pom文件引入包 2. web.xml 配置 3. 添加 spring-security.xml 文件 二、Spring Security实战应用 1. 项目结构 2. pom文件引入 3. web.xml 配置 4. Spring 配置 applicationContext.xml 5. sp…...

如何生成开发语言的排名图表

1、解释说明 生成开发语言排名图表&#xff0c;通常需要以下几个步骤&#xff1a; - 首先&#xff0c;我们需要收集一些关于不同编程语言的统计数据&#xff0c;例如使用人数、市场份额等。这些数据可以从各种来源获取&#xff0c;例如网站、报告、数据库等。 - 然后&#x…...

有哪些简单好用、适合中小型企业的CRM系统?

阅读本文&#xff0c;你将了解&#xff1a;一、中小型企业对CRM系统的主要需求&#xff1b;二、盘点四款好用的CRM系统&#xff1b;三、CRM系统实施策略和优秀实践。 在快速变化的商业环境中&#xff0c;中小型企业面临着独特的挑战&#xff1a;如何在有限的资源下高效地管理客…...

Unity 适配器模式(实例详解)

文章目录 简介1. **Input Adapter 示例**2. **Component Adapter 示例**3. **网络数据解析适配器**4. **物理引擎适配**5. **跨平台服务适配** 简介 Unity中的适配器模式&#xff08;Adapter Pattern&#xff09;主要用于将一个类的接口转换为另一个接口&#xff0c;以便于原本…...

Spring boot项目java bean和xml互转

Spring boot项目实现java bean和xml互转 项目场景&#xff1a;互转方法使用jackson进行互转使用jaxws进行xml与bean的互转 搞定收工&#xff01; 项目场景&#xff1a; 工作中需要给下游第三方收费系统做数据挡板&#xff0c;由于下游系统使用的是soap webservice,里面涉及各种…...

数字证书和数字证书认证机构和数字根证书,CA,RCA

文章目录 一、 数字证书1、什么是数字证书2、数字证书干什么的3、风险 二、数字证书认证机构&#xff08;Certificate Authority&#xff0c;缩写为CA&#xff09;参考文章 一、 数字证书 维基百科 公开密钥认证&#xff08;英语&#xff1a;Public key certificate&#xff…...

java web mvc-08-Grails 入门介绍

拓展阅读 Spring Web MVC-00-重学 mvc mvc-01-Model-View-Controller 概览 web mvc-03-JFinal web mvc-04-Apache Wicket web mvc-05-JSF JavaServer Faces web mvc-06-play framework intro web mvc-07-Vaadin web mvc-08-Grails 开源 The jdbc pool for java.(java …...

深度学习技术栈 —— Pytorch之TensorDataset、DataLoader

深度学习技术栈 —— Pytorch之TensorDataset、DataLoader 前言一、TensorDataset、DataLoader的用法&#xff1f;二、从.csv文件-->tensor张量总结 前言 简单来说&#xff0c;TensorDataset与DataLoader这两个类的作用&#xff0c; 就是将数据读入并做整合&#xff0c;以便…...

远程git开发

两种本地与远程仓库同步 """ 1&#xff09;你作为项目仓库初始化人员&#xff1a;线上要创建空仓库 > 本地初始化好仓库 > 建立remote链接(remote add) > 提交本地仓库到远程(push)2&#xff09;你作为项目后期开发人员&#xff1a;远程项目仓库已经创…...

Codeforces Round 812 (Div. 2) ---- C. Build Permutation --- 题解

目录 C. Build Permutation 题目描述&#xff1a; ​编辑 思路解析&#xff1a; 代码实现&#xff1a; C. Build Permutation 题目描述&#xff1a; 思路解析&#xff1a; 先证明在任何情况下答案均存在。 假设我们所求的为 m m1 m2.....n 的排列&#xff0c;我们称不小于n…...

Matlab 将工作区变量保存到文件中(save)

语法 1、save(filename) 2、save(filename,variables) 3、save(filename,variables,fmt) 4、save(filename,variables,version) 5、save(filename,variables,version,-nocompression) 6、save(filename,variables,-append) 7、save(filename,variables,-append,-nocompression…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...