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 来对作区分&…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...
