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

Spring:面向切面(AOP)

1. 代理模式

二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类**间接**调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——**解耦**。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护 

 

 

 

动态代理 

 

 

* 动态代理分为JDK动态代理和cglib动态代理
* 当目标类有接口的情况使用JDK动态代理和cglib动态代理,没有接口时只能使用cglib动态代理
* JDK动态代理动态生成的代理类会在com.sun.proxy包下,类名为$proxy1,和目标类实现相同的接口
* cglib动态代理动态生成的代理类会和目标在在相同的包下,会继承目标类
* 动态代理(InvocationHandler):JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求**代理对象和目标对象实现同样的接口**(兄弟两个拜把子模式)。
* cglib:通过**继承被代理的目标类**(认干爹模式)实现代理,所以不需要目标类实现接口。
* AspectJ:是AOP思想的一种实现。本质上是静态代理,**将代理逻辑“织入”被代理的目标类编译得到的字节码文件**,所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解。 

 

 2. AOP概述

AOP(Aspect Oriented Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善,它以通过预编译方式和运行期动态代理方式实现,在不修改源代码的情况下,给程序动态统一添加额外功能的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率 

相关术语 

横切关注点

这个概念不是语法层面的,而是根据附加功能的逻辑上的需要:有十个附加功能,就有十个横切关注点。

通知(功能):切入后要新添什么新的功能

切面:将通知(功能)封装成类

目标:被代理对象

代理:调用目标对象的功能,并且有自己的业务功能,即在目标基础上新加业务功能,但不需要修改目标对象的代码

切入点:通俗点来讲就是设置相对应的规则,满足该规则的方法就是要被代理的方法(也可理解为切入点,在哪个点(函数)切入新增功能)

 作用

* 简化代码:把方法中固定位置的重复的代码**抽取**出来,让被抽取的方法更专注于自己的核心功能,提高内聚性。
  
* 代码增强:把特定的功能封装到切面类中,看哪里有需要,就往上套,被**套用**了切面逻辑的方法就被切面给增强了。 

 3. 基于注解的AOP

业务场景模拟

原业务代码只能完成计算功能,在次基础上新增日志功能 

public interface Calculator {int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);
}
@Component
public class CalculatorImp implements Calculator{@Overridepublic int add(int i, int j) {int result = i + j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int sub(int i, int j) {int result = i - j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int mul(int i, int j) {int result = i * j;System.out.println("方法内部 result = " + result);return result;}@Overridepublic int div(int i, int j) {int result = i / j;System.out.println("方法内部 result = " + result);return result;}
}

 语法及细节

 

/**** 切入点表达式:"execution(权限修饰符. 返回值类型. 全类名. 方法名(形参类型))"* *  可以代表任意修饰符,任意返回值类型,任意方法,任意包,任意类* .. 代表任意方法的形参列表为任意类型* 如: execution(* com.itgyl.annoAop.CalculatorImp.*(..))* 即修饰符和返回类型任意的com.itgyl.annoAop这个包下的CalculatorImp这个类的所有方法形参列表任意的方法 调用时会执行这个前置方法*     execution(public int com.itgyl.annoAop.CalculatorImp.add(int, int))*     即修饰符为public 返回值类型为int 的com.itgyl.annoAop包下 的 CalculatorImp类 执行add(形参为两个int类型)这个方法时会先执行这个前置方法*/

 

/**** 通知:* 前置 @Before*      前置通知执行时机为代理方法执行前* 返回 @AfterReturning*      返回通知执行时机为代理方法调用结束正常返回结果后* 异常 @AfterThrowing*      异常通知执行时机为调用方法出现异常时执行* 后置 @After*      后置通知执行时机为代理方法调用完全结束后* 环绕 @Around*      环绕通知可以出现在代理方法前后中或异常等时机都能进行触发*      需手动调用proceed方法才会执行代理方法,并且代理方法的结果必须返回,不然报错*/
@Aspect    //该注解声明该类是一个切面类
@Component //通过该注解可以完成自动注入,放入IoC容器中
public class LogAspect {/**** JoinPoint切入点参数,该参数可以获取执行方法的名称,方法参数等等*///@Before("execution(public int com.itgyl.annoAop.*.*(..))")@Before(value = "execution(public int com.itgyl.annoAop.CalculatorImp.add(..))")public void beforeMethod(JoinPoint joinPoint) {String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("前置通知执行啦 执行方法为 " + name + " 参数为" + Arrays.toString(args));}@After("execution(* com.itgyl.annoAop.CalculatorImp.*(..))")public void afterMethod(JoinPoint joinPoint) {String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("后置通知执行啦 执行方法为 " + name + " 参数为" + Arrays.toString(args));}/**** returning:获取方法返回结果,返回结果的变量名随便取,但是下面执行的方法里的形参名要和该结果名保持一致* @param joinPoint 可通过该形参获取代理方法的内容* @param result    可通过该形参获取代理方法最终返回的结果*/@AfterReturning(value = "execution(* com.itgyl.annoAop.CalculatorImp.*(..))", returning = "result")public void afterReturningMethod(JoinPoint joinPoint, Object result) {String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("返回通知执行啦 执行方法为" + name + " 参数为" + Arrays.toString(args) + "返回结果为 " + result);}/**** 参数Throwable为异常信息,若添加该形参也需要在切入点表达式中绑定相应的形参* @param joinPoint 通过该形参可以获取代理方法的参数* @param e         通过该形参可以获取出现异常的信息*/@AfterThrowing(value = "execution(* com.itgyl.annoAop.CalculatorImp.*(..))", throwing = "e")public void afterThrowingMethod(JoinPoint joinPoint, Throwable e) {String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("异常通知执行啦 出现异常方法名为" + name + " 参数为" + Arrays.toString(args) + "异常信息为" + e);}@Around(value = "pointCut()")public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {String name = joinPoint.getSignature().getName();String args = Arrays.toString(joinPoint.getArgs());Object result = null;try {System.out.println("环绕通知执行(调用代理方法前) 方法名为" + name + "参数为 " + args);//调用代理方法后必须返回结果result = joinPoint.proceed();System.out.println("环绕通知执行(调用代理方法后) 方法名为" + name + "参数为 " + args);} catch (Exception e) {System.out.println("环绕通知执行(调用代理方法出现异常)");} finally {System.out.println("环绕通知执行(结束)");}return result;}/***重用切入点表达式:如果要代理方法值都一样时,可以将切入点表达式封装起来,后面可以直接调用该方法不需要每次重复写executing函数* 细节:如果当前切面类重用该切入点表达式可以直接调用该函数使用*      当其他类调用时需要全类名+该函数名才能调用*      如:@Around(value = "pointCut()")*          @Around(value = "com.itgyl.annoAop.LogAspect.pointCut()")*/@Pointcut(value = "execution(* com.itgyl.annoAop.CalculatorImp.*(..))")public void pointCut() {}
}

 测试类

public class TestAnnoAop {@Testpublic void testAdd() {ApplicationContext context =new ClassPathXmlApplicationContext("bean.xml");System.out.println(context);Calculator c = context.getBean(Calculator.class);System.out.println(c);c.add(2,3);}
}

执行结果 

 

切入点优先级 

 

4. 基于XML的AOP

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><context:component-scan base-package="com.itgyl.xmlAop"></context:component-scan><aop:config><!--配置切面类--><aop:aspect ref="logAspect"><!--配置切入点--><aop:pointcut id="pointCut" expression="execution(* com.itgyl.xmlAop.CalculatorImp.*(..))"/><!--配置通知--><!--配置前置通知,执行代理方法前要执行的方法为beforeMethod,切入点为上面配置的切入点表达式--><aop:before method="beforeMethod" pointcut-ref="pointCut"></aop:before><!--配置后置通知--><aop:after method="afterMethod" pointcut-ref="pointCut"></aop:after><!--配置异常通知,需绑定抛出异常的值,该值和函数中的异常形参名需保持一致--><aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointCut" throwing="e"></aop:after-throwing><aop:after-returning method="afterReturningMethod" pointcut-ref="pointCut" returning="result"></aop:after-returning><!--配置环绕通知--><aop:around method="aroundMethod" pointcut-ref="pointCut"></aop:around></aop:aspect></aop:config></beans>

相关文章:

Spring:面向切面(AOP)

1. 代理模式 二十三种设计模式中的一种&#xff0c;属于结构型模式。它的作用就是通过提供一个代理类&#xff0c;让我们在调用目标方法的时候&#xff0c;不再是直接对目标方法进行调用&#xff0c;而是通过代理类**间接**调用。让不属于目标方法核心逻辑的代码从目标方法中剥…...

本地镜像文件怎么导入docker desktop

docker tag d1134b7b2d5a new_repo:new_tag...

【机器学习-23】关联规则(Apriori)算法:介绍、应用与实现

在现代数据分析中&#xff0c;经常需要从大规模数据集中挖掘有用的信息。关联规则挖掘是一种强大的技术&#xff0c;可以揭示数据中的隐藏关系和规律。本文将介绍如何使用Python进行关联规则挖掘&#xff0c;以帮助您发现数据中的有趣模式。 一、引言 1. 简要介绍关联规则学习…...

Gradle筑基——Gradle Maven仓库管理

基础概念&#xff1a; 1.POM pom:全名Project Object Model 项目对象模型&#xff0c;用来描述当前maven项目发布模块的基础信息 pom主要节点信息如下&#xff1a; 配置描述举例&#xff08;com.android.tools.build:gradle:4.1.1&#xff09;groupId组织 / 公司的名称com.…...

c++11:智能指针的种类以及使用场景

指针管理困境 内存释放&#xff0c;指针没有置空&#xff1b;内存泄漏&#xff1b;资源重复释放 怎样解决&#xff1f; RAII 智能指针种类 shared_ptr 实现原理&#xff1a;多个指针指向同一资源&#xff0c;引用计数清零&#xff0c;再调用析构函数释放内存。 使用场景…...

RabbitMQ-默认读、写方式介绍

1、RabbitMQ简介 rabbitmq是一个开源的消息中间件&#xff0c;主要有以下用途&#xff0c;分别是&#xff1a; 应用解耦&#xff1a;通过使用RabbitMQ&#xff0c;不同的应用程序之间可以通过消息进行通信&#xff0c;从而降低应用程序之间的直接依赖性&#xff0c;提高系统的…...

阿里云百炼大模型使用

阿里云百炼大模型使用 由于阿里云百炼大模型有个新用户福利&#xff0c;有免费的4000000 tokens&#xff0c;我开通了相应的服务试试水。 使用 这里使用Android开发了一个简单的demo。 安装SDK implementation group: com.alibaba, name: dashscope-sdk-java, version: 2.…...

亲测有效,通过接口实现完美身份证号有效性验证+身份证与姓名匹配查询身份实名认证接口(实时)

最近发现一个限时认证的接口分享给大家&#xff0c;有需要的拿去试下吧. 附上部分密钥f478186edba9854f205a130aa888733d227a8f82f98d84b9【剩余约125450次&#xff0c;无时间限制】 b6131281611f6e1fc86c8662f549bdd683a68517203ba312【剩余约1300次&#xff0c;无时段限制】 …...

试题11 输出什么?

...

对vue3/core源码ref.ts文件API的认识过程

对toRef()API的认识的过程: 最开始认识toRef()是从vue3源码中的ref.ts看见的,右侧GPT已经举了例子 然后根据例子,在控制台输出ref对象是什么样子的: 这就是ref对象了,我们根据对象中有没有__v_isRef来判断是不是一个ref对象,当对象存在且__v_isRef true的时候他就判定为是一个…...

AWS迁移与传输之AWS DMS

AWS Database Migration Service&#xff08;AWS DMS&#xff09;是一项托管的服务&#xff0c;用于帮助企业将现有的数据库迁移到AWS云中的各种数据库引擎中&#xff0c;或者在不同数据库引擎之间进行数据迁移和同步。直接在线迁移&#xff0c;将数据复制到云端&#xff0c;不…...

【ML Olympiad】预测地震破坏——根据建筑物位置和施工情况预测地震对建筑物造成的破坏程度

文章目录 Overview 概述Goal 目标Evaluation 评估标准 Dataset Description 数据集说明Dataset Source 数据集来源Dataset Fields 数据集字段 Data Analysis and Visualization 数据分析与可视化Correlation 相关性Hierarchial Clustering 分层聚类Adversarial Validation 对抗…...

kafka监控配置和告警配置

Kafka的监控配置和告警配置是确保Kafka集群稳定运行的关键部分。以下是一些关于Kafka监控配置和告警配置的建议&#xff1a; 一、Kafka监控配置 集群级别参数监控&#xff1a; log.retention.hours&#xff1a;用于控制消息在日志中保留的时间。监控此参数的值&#xff0c;确…...

关于智慧校园安全用电监测系统的设计

人生人身安全是大家关注的话题&#xff0c;2019年12月中国消防统计近五年发生在全国学生宿舍的火灾2314起&#xff08;中国消防2019.12.应急管理部消防救援局官方微博&#xff09;&#xff0c;违规电器是引发火灾的主因。如果在各寝室安装智能用电监测器实时监督线路参数&#…...

Flutter 中的 FormField 小部件:全面指南

Flutter 中的 FormField 小部件&#xff1a;全面指南 在Flutter的世界里&#xff0c;表单是用户输入数据的基本方式之一。FormField是一个强大的小部件&#xff0c;它将表单字段的创建、验证和管理集成到了一个易于使用的抽象中。本文将为您提供一个全面的指南&#xff0c;帮助…...

数据库DCL语句

数据库DCL语句 介绍&#xff1a; DCL英文全称是Data Control Language(数据控制语言)&#xff0c;用来管理数据库用户、控制数据库的访 问权限。 管理用户&#xff1a; 查询用户: select * from mysql.user;创建用户: create user 用户名主机名 identified by 密码;修改用…...

mysql-日志管理-error.log

日志管理 默认的数据库日志 vim /etc/my.cnf //错误日志 log-error/usr/local/mysql/mysql.log查看数据库日志 tail -f /usr/local/mysql/mysql.log1 错误日志 &#xff1a;启动&#xff0c;停止&#xff0c;关闭失败报错。rpm安装日志位置 /var/log/mysqld.log #默认开启 2 …...

弱密码系统登录之后强制修改密码

在你登录的时候&#xff0c;获取到弱密码&#xff0c;然后将他存到vuex里面&#xff0c;在登录进去之后&#xff0c;index页面再去取&#xff0c;思路是这样的 一、vuex里面定义密码字段 我是直接在user.js里面写的 import { login, logout, getInfo } from /api/login impo…...

解释Python中的多线程和多进程编程

在Python中&#xff0c;多线程&#xff08;Multithreading&#xff09;和多进程&#xff08;Multiprocessing&#xff09;是两种常见的并发编程技术&#xff0c;用于同时执行多个任务。然而&#xff0c;由于Python的全局解释器锁&#xff08;GIL&#xff0c;Global Interpreter…...

【LeetCode】【1】两数之和(1141字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现哈希表 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给定一个整数数组nums和一个整数目标值target&#xff0c;请在该数组中找出…...

AMLP:基于大语言模型的自动化机器学习势函数构建平台

1. 项目概述&#xff1a;当AI遇见原子模拟&#xff0c;AMLP如何重塑机器学习势函数构建在计算材料科学和化学物理领域&#xff0c;分子动力学模拟是我们窥探微观世界动态行为的“显微镜”。无论是研究新材料的相变过程&#xff0c;还是探索生物大分子的折叠机制&#xff0c;其核…...

Arduino PWM转4-20mA工业电流信号:二阶滤波与V/I转换电路设计

1. 项目概述&#xff1a;从PWM到工业标准电流信号在工业自动化、过程控制和传感器领域&#xff0c;4-20 mA电流环是一个几乎无处不在的标准。它用4 mA代表测量值的下限&#xff08;如0C&#xff09;&#xff0c;20 mA代表上限&#xff08;如100C&#xff09;&#xff0c;这种设…...

Java数组工具类实战:设计不可实例化的静态工具类

实现一个工具类 MathUtils&#xff0c;满足以下要求&#xff1a; 1. 所有方法均为静态&#xff0c;且该类不能从外部实例化&#xff08;提示&#xff1a;使用私有构造器&#xff09;。 2. 提供三个静态方法&#xff1a;- maxArray(int[] arr)&#xff1a;返回较大值&#xff1b…...

终极Node.js Mock工具:Mockery入门到精通实战教程

终极Node.js Mock工具&#xff1a;Mockery入门到精通实战教程 【免费下载链接】mockery Simplifying the use of mocks with Node.js 项目地址: https://gitcode.com/gh_mirrors/mock/mockery Mockery是Node.js生态中简化Mock使用的终极工具&#xff0c;它为开发者提供了…...

基于C#实现(WinForm)P2P聊天程序

♻️ 资源 大小&#xff1a; 29.8MB ➡️ 资源下载&#xff1a;https://download.csdn.net/download/s1t16/87430269 p2p聊天程序 一、功能介绍 1.1 登录 用户凭用户名和密码登录系统&#xff0c;可以更换服务器 IP 和端口&#xff0c;以防网络不畅通&#xff0c;连接服务…...

如何快速定制Office界面:终极开源工具使用指南

如何快速定制Office界面&#xff1a;终极开源工具使用指南 【免费下载链接】office-ribbonx-editor An overhauled fork of the original Custom UI Editor for Microsoft Office, built with WPF 项目地址: https://gitcode.com/gh_mirrors/of/office-ribbonx-editor O…...

【Midjourney霓虹效果终极指南】:20年AI视觉工程师亲授5大参数组合+3类光源建模公式,97%新手一周内复刻赛博朋克海报

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;霓虹美学的视觉原理与Midjourney适配性解析 霓虹美学源于20世纪都市夜景中的荧光灯管、电子广告与赛博朋克文化&#xff0c;其核心视觉特征包括高饱和度冷暖对比、边缘辉光&#xff08;glow&#xff09;、深色…...

基于ESP32与MQTT的智能时钟:从硬件驱动到物联网系统集成实战

1. 项目概述&#xff1a;一个基于ESP32和MQTT的智能卧室时钟几年前&#xff0c;我在一个旧货市场淘到了四块巨大的SA40-19SRWA七段数码管&#xff0c;它们一直躺在我的零件箱里吃灰。直到ESP32这颗功能强大的物联网芯片变得唾手可得&#xff0c;我才终于为它们找到了完美的归宿…...

混合物理-ML辐射方案:攻克气候模型中次网格云效应的新范式

1. 项目概述与核心挑战在气候模拟这个庞大的数字沙盘中&#xff0c;地球系统模型&#xff08;ESM&#xff09;是我们理解未来气候演变的核心工具。然而&#xff0c;这个沙盘有一个长期存在的“颗粒度”难题&#xff1a;受限于计算资源&#xff0c;模型的水平分辨率通常在100到2…...

OpenPLC虚拟PLC:5分钟搭建开源工业控制器的完整指南

OpenPLC虚拟PLC&#xff1a;5分钟搭建开源工业控制器的完整指南 【免费下载链接】OpenPLC Software for the OpenPLC - an open source industrial controller 项目地址: https://gitcode.com/gh_mirrors/op/OpenPLC 想要零成本学习工业自动化&#xff1f;OpenPLC虚拟PL…...