Spring的AOP开发-基于xml配置的AOP
Spring的AOP开发-基于xml配置的AOP
xml方式AOP快速入门
通过配置文件的方式解决以下问题
- 配置哪些包、哪些类、哪些方法需要被增强
- 配置目标方法要被哪些通知方法所增强,在目标方法执行之前还是之后执行增强
配置方式的设计、配置文件(注解),Spring已经帮我们封装好了
xml方式配置AOP的步骤:
1、 导入AOP相关坐标;
2、准备目标类、准备增强类,并配置给Spring管理;
3、配置切点表达式(哪些方法被增强);
4、配置织入(切点被哪些通知方法增强,是前置增强还是后置增强)。
package com.luxifa.service;
public interface UserService {void show1();void show2();}
package com.luxifa.service.impl;
public class UserServiceImpl implements UserService {@Overridepublic void show1() {System.out.println("show1...")}@Overridevoid show2() {System.out.println("show2...")}}
package com.luxifa.advice;//增强类.内部提供增强方法
public class MyAdvice {public void beforeAdvice() {System.out.println("前置的增强...");}public void afterAdvice() {System.out.println("后置的增强...");}
}
<!--配置目标类-->
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl"/><bean>
<!--配置的通知类-->
<bean id="myAdvice" class="com.luxifa.advice.MyAdvice"></bean><!--aop配置-->
<aop:config><!--配置切点表达式,目的是要指定哪些方法被增强--><aop:pointcut id="myPoincut" expression="execution(void com.luxifa.service.impl.UserServiceImpl.show1())"/><!--配置织入,目的是要执行哪些切点与哪些通知进行结合--><aop:aspect ref="myAdvice"><aop:before method="beforeAdvice" pointcut-ref="myPointcut"/></aop:aspect>
</aop:config>
测试类:
public class ApplicationContextTest {public static void main(String[] args) {ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = app.getBean(UserService.class);userService.show1();}
}
控制台打印:
前置的增强....
show1....
xml方式AOP配置详解
- 切点表达式的配置方式
切点表达式的配置方式有两种,直接将切点表达式配置在通知上,也可以将切点表达式抽取到外面,在通知上进行引用
<aop:config><!--配置切点表达式,对哪些方法进行增强--><aop:pointcut id="myPoincut" expression="execution(void com.luxifa.service.impl.UserServiceImpl.show1())"/><!--切面=切点+通知--><aop:aspect ref="myAdvice"><!--指定前置通知方法是beforeAdvice--><aop:before method="beforeAdvice" pointcut-ref="myPointcut"/><!--指定后置通知方法是afterAdvice--><aop:after-returning method="afterAdvice" pointcut="excution(void com.luxifa.service.impl.UserServiceImpl.show1())"/></aop:aspect>
</aop:config>
- 切点表达式的配置语法
切点表达式是配置要对哪些连接点(哪些类的哪些方法)进行通知的增强,语法如下:
execution([访问修饰符]返回值类型 包名.类名.方法名(参数))
其中:
- 访问修饰符可以省略不写;
- 返回值的类型、某一级包名、类名、方法名 可以使用*表示任意;
- 包名与类型之间使用单点 . 表示该包下的累,使用双点 … 表示该包及其子包下的类;
- 参数列表可以使用两个点 … 表示任意参数。
切点表达式举例:
//表示访问修饰符为public、无返回值、在com.luxifa.aop包下的TargetImpl类的无参方法show
execution(public void com.luxifa.aop.TargetImpl.show())//表示com.luxifa.aop包下的TargetImpl类的任意方法
execution(* com.luxifa.aop.TargetImpl.*.(..))//表示com.luxifa.aop包下的任意类的任意方法
execution(* com.luxifa.aop.*.*(..))//表示om.luxifa.aop包及其子包下的任意类的任意方法
execution(* com.luxifa.aop..*.*(..))//表示任意包中的任意类的任意方法
execution(* *..*.*(..))
- 通知的类型
AspectJ的通知由以下五种类型
| 通知名称 | 配置方式 | 执行时机 |
|---|---|---|
| 前置通知 | aop:before | 目标方法执行之前执行 |
| 后置通知 | aop:after-returning | 目标方法执行之后执行,目标方法异常时,不再执行 |
| 环绕通知 | aop:around | 目标方法执行前后执行,目标方法异常时,环绕后方法不再执行 |
| 异常通知 | aop:after-throwing | 目标方法抛出异常时执行 |
| 最终通知 | aop:after | 不管目标方法是否有异常,最终都会执行 |
环绕通知:
package com.luxifa.service;
public interface UserService {void show1();void show2();}
package com.luxifa.service.impl;
public class UserServiceImpl implements UserService {@Overridepublic void show1() {System.out.println("show1...")}@Overridevoid show2() {System.out.println("show2...")}}
package com.luxifa.advice;//增强类.内部提供增强方法
public class MyAdvice {public void beforeAdvice() {System.out.println("前置的增强...");}public void afterReturningAdvice() {System.out.println("后置的增强...");}public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("环绕前的增强...");//执行目标方法Object res = proceedingJoinPoint.proceed();System.out.println("环绕后的增强...");return res;}
}
<!--配置目标类-->
<bean id="userService" class="com.luxifa.service.impl.UserServiceImpl"/><bean>
<!--配置的通知类-->
<bean id="myAdvice" class="com.luxifa.advice.MyAdvice"></bean><!--aop配置-->
<aop:config><!--配置切点表达式,目的是要指定哪些方法被增强--><aop:pointcut id="myPoincut" expression="execution(void com.luxifa.service.impl.UserServiceImpl.show1())"/><aop:pointcut id="myPoincut2" expression="execution(* com.luxifa.service.impl.*.*(..))"/><!--配置织入,目的是要执行哪些切点与哪些通知进行结合--><aop:aspect ref="myAdvice"><!--环绕通知合--><aop:around method="around" pointcut-ref="myPointcut2"/></aop:aspect>
</aop:config>
通知方法在被调用时,Spring可以为其传递一些必要的参数
| 参数类型 | 作用 |
|---|---|
| JoinPoint | 连接点对象,任何通知都可使用,可以获得当前目标对象、目标方法参数等信息 |
| ProceedingJoinPoint | JoinPoint子类对象,主要是在环绕通知中执行proceed(),进而执行目标方法 |
| Throwable | 异常对象,使用在异常通知类中,需要在配置文件中指出异常对象名称 |
JointPoint对象
public void 通知方法名称(JointPoint joinPoint) {//获得目标方法的参数System.out.println(joinPoint.getArgs());//获得目标对象System.out.println(joinPoint.getTarget());//获得精确的切点表达式信息System.out.println(joinPoint.getStaticPart());
}
ProceedingJoinPoint对象
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//获得目标方法的参数System.out.println(joinPoint.getArgs());//获得目标对象System.out.println(joinPoint.getTarget());//获得精确的切点表达式信息System.out.println(joinPoint.getStaticPart());//执行目标方法Object result = joinPoint.proceed();//返回目标方法返回值return result;
}
Throwable 对象
public void afterThrowing(JointPoint joinPoint,Throwable th) {//获得异常信息System.out.println("异常对象是:"+th+"异常信息是:"+th.getMessage());
}
<aop:after-throwing method="afterThrowing" pointcut-ref="mypointcut" throwing="th"/>
- AOP的配置的两种方式
AOP配置的两种语法形式
AOP的xml有两种配置方式,如下:
- 使用advisor配置切面
- 使用aspect配置切面
Spring定义了一个Advice接口,实现了该接口的类都可以作为通知类出现
public interface Advice{
}
advisor需要的通知类需要实现Advice的子功能接口,例如:MethodBeforeAdvice、AfterReturningAdvice等,是通过实现的接口去确定具备哪些通知增强的。
AOP配置的两种语法形式不同点
语法形式不同:
- advisor是通过实现接口来确定通知的类型
- aspect是通过配置确认通知的类型,更加灵活
可配置的切面数量不同:
- 一个advisor只能配置一个固定通知和一个切点表达式
- 一个aspect可以配置多个通知和多个切点表达式任意组合
使用场景不同:
- 允许随意搭配情况下可以使用aspect进行配置
- 如果通知类型单一、切面单一的情况下可以使用advisor进行配置
- 在通知类型已经固定,不用人为指定通知类型时,可以使用advisor进行配置,例如Spring事务控制的配置
xml方式AOP原理剖析
两种生成动态代理对象的方式,一种是基于JDK,一种基于Chlib
| 代理技术 | 使用条件 | 配置方式 |
|---|---|---|
| JDK动态代理技术 | 目标类有接口,是基于接口动态生成实现类的代理对象 | 目标类有接口的情况下,默认方式 |
| Cglib动态代理技术 | 目标类无接口且不能使用final修饰,是基于被代理对象动态生成子对象为代理对象 | 目标类无接口时,默认使用该方式;目标类有接口时,手动配置aop:config |
Cglib基于超类的动态代理
//目标对象
Target target = new Target();
//通知对象
Advices advices = new Advices();
//增强器对象
Enhancer enhancer = new Enhancer();
//增强器设置父类
enhancer.setSuperclass(Target.class);
//增强器设置回调
enhancer.setCallback((MethodInterceptor)(o.method.methodProxy)->{advice.before();Object object = method.invoke(target,Objects);advice.afterReturning();return result;
});
//创建代理对象
Target targetProxy = (Target)enhancer.create();
//测试
String result = targetProxy.show("路西法");
相关文章:
Spring的AOP开发-基于xml配置的AOP
Spring的AOP开发-基于xml配置的AOP xml方式AOP快速入门 通过配置文件的方式解决以下问题 配置哪些包、哪些类、哪些方法需要被增强配置目标方法要被哪些通知方法所增强,在目标方法执行之前还是之后执行增强 配置方式的设计、配置文件(注解),Spring已…...
JAVA的垃圾收集器与内存分配策略【一篇文章直接看懂】
内存动态分配和垃圾收集技术是JAVA和C之间最大的区别之一 垃圾收集(Garbage Collection,GC)只办三件事: 哪些内存需要回收什么时候回收如何回收 对于对象回收的方法 引用计数法: 每处引用时1,引用失效…...
NLP学习——信息抽取
信息抽取 自动从半结构或无结构的文本中抽取出结构化信息的任务。常见的信息抽取任务有三类:实体抽取、关系抽取、事件抽取。 1、实体抽取 从一段文本中抽取出文本内容并识别为预定义的类别。 实体抽取任务中的复杂问题: 重复嵌套,原文中…...
【深度学习基础7】预训练、激活函数、权重初始化、块归一化
一、Unsupervised Pre-training 得益于 Hinton and Salakhutdinov 在 2006 年的开创性工作— 无监督预训(unsupervised pre-training);在《Reducing the dimensionality of data with neural networks.》这篇论文中,他们在 RBMs 中引入无监督预训练,下面我们将在Autoenco…...
MetaMQ
文章目录MetaMQMetaMQ 的优势在于:MetaMQ 的劣势也有:MetaMQ MetaMQ 是一个基于以太坊的可扩展分布式消息队列(MQ)系统,它可以支持大规模的分布式应用程序。MetaMQ 是一个开放源代码项目,它支持企业级应用程…...
热门盘点 | 10款评分最高的项目管理工具
项目管理软件可以让项目经理及时掌握项目进展可把复杂的任务分解简单帮助项目经理及时了解整个团队进展随着现代项目需求日趋复杂和个性选一个好的项目管理软件还是很有必要的① PingCode国内研发项目管理软件PingCode,它是国内软件研发项目榜单中评分最高的项目管理…...
若依框架---分页功能
继前几天我们学习若依管理系统中的代码生成工具,我们发现若依系统中还要很多值得学习的地方。今天我们来学习若依管理系统中的分页工具。 若依管理系统是前后端分离的(准确的说,若依有前后端分离版本)。 前端 若依前端的分页没…...
CHAPTER 3 Jenkins SVN GItlab
Jenkins SVN GItlab3.1 JenkinsSVN3.1.1 搭建SVN服务器1. 安装svn server2. 查看svn安装位置3. 创建版本库目录4. 创建svn版本库5. 配置修改6. 防火墙开启3690端口7. 启动SVN-server8. 客户端访问svn服务器3.1.2 测试脚本提交3.1.3 jenkins下载代码配置1. 安装Subversion插件2.…...
为什么Redis集群的最大槽数是16384个?
对于客户端请求的key,根据公式HASH_SLOTCRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作! 为什么有16384个槽? Redis集群并没有使用一致性hash而是引入了哈希槽的概念。Redis 集群有16…...
餐饮企业数据可视化大屏(智慧餐饮)
随着信息技术的深入发展,数据大屏的适用场景日益广泛,集工作汇报、实时监控和预测分析等功能于一身。 数据可视化的本质是视觉对话,数据可视化将数据分析技术与图形技术结合,清晰有效地将分析结果信息进行解读和传达。 当前很多餐…...
Kafka安装及zookeeper is not a recognized option问题解决
一安装JAVA JDK(略) 二安装ZooKeeper 下载安装包,建议bin版本 http://zookeeper.apache.org/releases.html#download解压并进入ZooKeeper,将“zoo_sample.cfg”重命名为“zoo.cfg” D:\Kafka\apache-zookeeper-3.7.1-bin\conf…...
leetcode刷题 | 关于二叉树的题型总结1
leetcode刷题 | 关于二叉树的题型总结1 文章目录leetcode刷题 | 关于二叉树的题型总结1题目连接完全二叉树插入器在每个树行中找最大值找树左下角的值二叉树的右视图二叉树剪枝题目连接 919. 完全二叉树插入器 - 力扣(LeetCode) 515. 在每个树行中找最…...
webpack新手入门
前言: 如何配置webpack呢? webpack概念有哪些呢? 怎么快速理解并使用webpack呢? 文章目录一. 什么是webpack二. 安装webpack三. webpack的五个核心概念四. webpack配置五. loader加载器1. css处理2. 处理文件(图片&…...
Redis中有常见数据类型
Redis的数据类型 string数据类型 string是redis最基本的类型,而且string类型是二进制安全的。意思是redis的string可以包含任何 数据,比如jpg图片或者序列化的对象 String类型是最基本的数据类型,一个redis中字符串value最多可以是512M r…...
【知识梳理】Go语言核心编程
基础知识 Go语言就是为了解决编程语言对并发支持不友好、编译速度慢、编程复杂这三个问题而诞生的 特点: Go语言选择组合思想,抛弃继承关系通过接口组合,自由组合成新接口,用接口实现层与层之间的解耦语言特性对比: package mainimport "fmt"func main() {fmt…...
Java中动态调用setter以及getter
0x00 前言 对于非专业程序员的安全人员来说,因为没有代码项目的积累,很多知识体系都不完善,所以有必要在一些常用的内容进行学习的总结。 在很多的调用链中都会用到**“动态调用setter以及getter”**这个知识点,比如经典的CB链&a…...
基于 NeRF 的 App 上架苹果商店!照片转 3D 只需一部手机,网友们玩疯了
前言 只用一部手机,现实中的 2D 照片就能渲染出 3D 模型? 没错,无需再手动上传电脑或安装激光雷达,苹果手机自带 App 就能生成 3D 模型。 这个名叫 Luma AI 的“NeRF APP”,正式上架 App Store 后爆火: 小…...
C++类与对象(中)
✅<1>主页:我的代码爱吃辣 📃<2>知识讲解:C 🔥<3>创作者:我的代码爱吃辣 ☂️<4>开发环境:Visual Studio 2022 💬<5>前言:C类中一共有六个默认成员函…...
计算机软件技术基础复习
数据结构 文章目录数据结构第一节 数据结构的基本概念第二节 线性结构线性表顺序表和链表的特点实现循环队列第三节 非线性结构树操作系统操作系统概述进程和程序存储空间的组织数据库技术数据库设计软件技术软件生命周期第一节 数据结构的基本概念 数据结构:指相互…...
python爬虫--beautifulsoup模块简介
BeautifulSoup 的引入 我们学习了正则表达式的相关用法,但是一旦正则写的有问题,可能得到的就不是我们想要的结果了,而且对于一个网页来说,都有一定的特殊的结构和层级关系,而且很多标签都有 id 或 class 来对作区分&…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
