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

Spring之AOP实现

1. AOP的实现方式

  1. 使用AspectJ的编译器来改动class类文件实现增强(使用不广泛) ----- 编译阶段

    这种对class类文件增强的, 也可以增强static静态方法, 而通过代理方式就无法实现静态方法的增强

    可通过查看编译后class文件反编译后的java代码验证

  2. agent增强(使用不广泛) ----- 类加载阶段

这种方式的增强也会使得代理类在内部自己调用自己的方法也获得增强, 原因是这种方式是通过类加载阶段进行的增强, 在通过this.xxFunc()调用自己本类的方法也是触发代理类的方法。

可通过arthas等工具查看jvm内存中增强后的类的反编译后的java代码验证

  1. Proxy代理方式实现AOP(绝大多数的选择)
  • JDK 代理 (只能代理实现了接口的类, 而且也只能代理那些接口方法, 代理类与目标类同级关系)
  • CGLIB 代理 (能代理类和接口, 但该类或代理的方法不能使用final修饰, 因为是基于继承进行增强的, 代理类与目标类是父 / 子 关系)

代理创建的两个时机:

  1. 初始化之后
  2. 实例创建之后, 依赖注入之前(有循环依赖时), 并暂存于二级缓存 earlySingletonObjects

JDK实现的代理:

public class JdkProxyDemo {interface Foo{void foo();}// 将被用作jdk代理的实例类static class Target implements Foo{@Overridepublic void foo() {System.out.println("target foo");}// 这个方法无法被代理,因为不是来自接口的方法public void test(){System.out.println("test");}}// jdk代理 只能针对接口代理// cglib代理public static void main(String[] args) {// 目标对象Target target = new Target();ClassLoader classLoader = JdkProxyDemo.class.getClassLoader();//用来加载在运行期间动态生成的字节码Foo proxyInstance = (Foo) Proxy.newProxyInstance(classLoader, new Class[]{Foo.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before...");// 目标.方法(参数)// method.invoke(proxy, args); 错误写法, 这里的proxy代表代理类自身, 传入proxy会陷入无限循环Object result = method.invoke(target, args);System.out.println("after...");return result;}});proxyInstance.foo();}
}

Cglib实现的代理:

注意: 在MethodInterceptor实现的intercept()方法中,传入了一个参数methodProxy, 通过该对象调用methodProxy.invoke(target, args)也能执行目标对象, 但其内部不是通过反射的方式。

public class CglibProxyDemo {static class Target{public void foo(){System.out.println("target foo");}}public static void main(String[] args){Target target = new Target();Target proxyInstance = (Target) Enhancer.create(Target.class, new MethodInterceptor() {@Overridepublic Object intercept(Object proxy, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("before...");Object result = method.invoke(target, args); //Spring使用的方式//Object result = methodProxy.invoke(target, args); 非反射方式调用, 而且可以不用目标就调用System.out.println("after...");return result;}});proxyInstance.foo();}
}

2.Spring中的两种切面

@Aspect: 高级切面, 可以包含多组通知和切面

Advisor: 低级切面, 适合框架内部使用, 只有一个通知和一个切面

Spring在处理这两个切面时, @Aspect切面最终还是转为Advisor

两种方式使用示例:

public class AspectDemo {public static void main(String[] args) {GenericApplicationContext context = new GenericApplicationContext();context.registerBean("aspect1", Aspect1.class);context.registerBean("config", Config.class);context.registerBean(ConfigurationClassPostProcessor.class);context.refresh();for (String beanDefinitionName : context.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}static class Target1{public void foo(){System.out.println("target1 foo");}}static class Target2{public void bar(){System.out.println("target bar");}}//高级切面,Aspect@Aspectstatic class Aspect1{@Before("execution(* foo())")public void before(){System.out.println("aspect1 before...");}@After("execution(* foo())")public void after(){System.out.println("aspect1 after...");}}//低级切面, 由一个切点(AspectJExpressionPointcut)和一个通知(MethodInterceptor)组成@Configurationstatic class Config{@Beanpublic Advisor advisor3(MethodInterceptor advice3){AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression("execution(* foo())");return new DefaultPointcutAdvisor(pointcut , advice3);}@Beanpublic MethodInterceptor advice3(){return new MethodInterceptor() {@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {System.out.println("advice3 before...");Object result = methodInvocation.proceed();System.out.println("advice3 after...");return result;}};}}
}

相关文章:

Spring之AOP实现

1. AOP的实现方式 使用AspectJ的编译器来改动class类文件实现增强(使用不广泛) ----- 编译阶段 这种对class类文件增强的, 也可以增强static静态方法, 而通过代理方式就无法实现静态方法的增强 可通过查看编译后class文件反编译后的java代码验证 agent增强(使用不广泛) ----- 类…...

Spring之基于xml的自动装配、基于Autowired注解的自动装配

文章目录基于xml的自动装配①注解②扫描③新建Maven Module④创建Spring配置文件⑤标识组件的常用注解⑥创建组件⑦扫描组件⑧测试⑨组件所对应的bean的id基于注解的自动装配①场景模拟②Autowired注解③Autowired注解其他细节④Autowired工作流程Autowire 注解的原理Qualifier…...

【案例】--(非分布式)轻量级任务调度平台

目录 一、前言说明二、背景2.1、完成任务,顺便搭建了一个任务调度平台三、具体实现解析3.1、技术栈等选型3.2、完成具体功能解析(1)、支持基本任务功能(2)、支持日志收集功能(3)、支持用户异常,选择性关闭调度功能(4)、实时监控正在执行和任务队列的任务情况(5)、实时监控任务…...

key的作用原理与列表的遍历、追加、搜索、排序

目录 一、key的作用原理 二、实现列表遍历并对在列表最前方进行追加元素 三、实现列表过滤搜索 1、用computed计算属性来实现 2、用watch监听输入值的变化来实现 四、按年龄排序输出列表 一、key的作用原理 1. 虚拟DOM中key的作用: key是虚拟DOM对象的标识&a…...

SQL性能优化的47个小技巧,你了解多少?

收录于热门专栏Java基础教程系列(进阶篇) 1、先了解MySQL的执行过程 了解了MySQL的执行过程,我们才知道如何进行sql优化。 客户端发送一条查询语句到服务器;服务器先查询缓存,如果命中缓存,则立即返回存…...

DPDK — 数据加速方案的核心思想

目录 文章目录 目录DPDK 数据加速方案1、使用用户态协议栈来代替内核协议栈Linux UIO FrameworkDPDK UIO Framework2、使用轮训来代替中断Kernelspace igb_uio DriverUserspace PMD3、使用多核编程代替多线程无锁环队列:CPU 核间无锁通信DPDK 数据加速方案...

[python入门㊽] - 自定义异常 raise 关键字

目录 ❤ 自定义抛出异常关键字 - raise ❤ 使用raise主动引发异常 ❤ raise 关键字的用法 ❤ 触发异常 ❤ 自定义异常类 在前面我们学过异常三个关键字分别是try、except 以及 finally 在编程过程中合理的使用异常可以使得程序正常的执行。有直接抛出异常的形式&…...

DDOS攻击

注:本博客只是为了自己的学习,记录自己的学习,请勿用于其他途径、1、winR-->cmd2、ping 网站3、替换IP1 import java.io.BufferedInputStream;2 import java.io.IOException;3 import java.net.MalformedURLException;4 import java.net.U…...

网络编程套接字

文章目录1. socket编程接口1-1 socket 常见API1-2 sockaddr结构2. 简单的UDP网络程序2-1 日志(固定用法:标准部分自定义部分)2-2 服务器代码实现1. 框架2. 初始化服务器3. 服务器运行4. 调用服务器封装函数(UdpServer)…...

海量数据相似数据查询方法

1、海量文本常见 海量文本场景,如何寻找一个doc的topn相似doc,一般存在2个问题, 1)、两两对比时间o(n^2) 2)、高维向量比较比较耗时。 文本集可以看成(doc,word)稀疏矩阵,一般常见的方法是构建到排索引,然后进行归并…...

Codeforces Round #822 (Div. 2)

A(签到) - Select Three Sticks 题意: 给你一个长度为 n 的正整数序列,你可以操作任意次,每一次操作可以选择任意一个元素,把它 1 或者 - 1,问最少多少次操作可以使得序列中存在三个相同的数字以构成一个等边三角形.…...

华为OD机试 - 最短木板长度(JS)

最短木板长度 题目 小明有 n n n块木板,第 i i i(1≤ i i </...

java设计模式——观察者模式

概述 定义:又被称为发布-订阅(Publish/Subscribe)模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时&#xff0c;会通知所有的观察者对象&#xff0c;使他们能够自动更新自己。 结构 在观察者模式…...

linux高级命令之线程的注意点

线程的注意点学习目标能够说出线程的注意点1. 线程的注意点介绍线程之间执行是无序的主线程会等待所有的子线程执行结束再结束线程之间共享全局变量线程之间共享全局变量数据出现错误问题2. 线程之间执行是无序的import threading import timedeftask():time.sleep(1)print(&qu…...

MyBatisPlus ---- 多数据源

MyBatisPlus ---- 多数据源1. 创建数据库及表2. 引入依赖3. 配置多数据源4. 创建用户service5. 创建商品service6. 测试适用于多种场景&#xff1a;纯粹多库、读写分离、一主多从、混合模式等 目前我们就来模拟一个纯粹多库的一个场景&#xff0c;其他场景类似 场景说明&#x…...

Java多线程

目录1 多线程1.1 进程1.2 线程1.3 多线程的实现方式1.3.1 方式1&#xff1a;继承Tread类1.3.2 方式2&#xff1a;实现Runnable接口1.3.3 方式3&#xff1a;实现Callable接口1.4 设置和获取线程名称1.5 线程调度1.6 线程控制1.7 线程生命周期1.8 数据安全问题之案例&#xff1a;…...

linux高级命令之线程执行带有参数的任务

线程执行带有参数的任务学习目标能够写出线程执行带有参数的任务1. 线程执行带有参数的任务的介绍前面我们使用线程执行的任务是没有参数的&#xff0c;假如我们使用线程执行的任务带有参数&#xff0c;如何给函数传参呢?Thread类执行任务并给任务传参数有两种方式:args 表示以…...

管理会计报告和财务报告的区别

财务会计报告是给投资人看的&#xff0c;可以反映公司总体的盈利能力。不过&#xff0c;我们回顾一下前面“第一天”里面提到的问题。如果你是公司的产品经理&#xff0c;目前有三个产品在你的管辖范围内。上级给你一笔新的资金&#xff0c;这笔资金应该投到哪个产品上&#xf…...

华为OD机试 - 最左侧冗余覆盖子串(Python) | 机试题算法思路 【2023】

最近更新的博客 华为OD机试 - 自动曝光(Python) | 机试题算法思路 【2023】 华为OD机试 - 双十一(Python) | 机试题算法思路 【2023】 华为OD机试 - 删除最少字符(Python) | 机试题算法思路 【2023-02】 华为OD机试 - Excel 单元格数值统计(Python) | 机试题算法思路 …...

【Opencv 系列】第1章 图像基础

通过本套课程,可以学到: 1.opencv的基本操作 2.两个案例,目标追踪&人脸识别 对重点内容,我会提示,包括我再准备这套课程过程中遇到的坑点! 最后代码我会放到git上,章节顺序一致:https://github.com/justinge/opencv_tutorial.git 系列文章目录 第1章 Opencv 图像基础 和 …...

保姆级教程:在UniApp中集成FFmpeg 7.1播放RTSP流(Android原生插件实战)

保姆级教程&#xff1a;在UniApp中集成FFmpeg 7.1播放RTSP流&#xff08;Android原生插件实战&#xff09; 跨平台开发中遇到RTSP流媒体播放需求时&#xff0c;UniApp官方组件往往力不从心。本教程将手把手带你突破这一技术瓶颈&#xff0c;通过Android原生插件集成FFmpeg 7.1实…...

AI人脸生成新范式:IP-Adapter-FaceID PlusV2双重嵌入技术解析

AI人脸生成新范式&#xff1a;IP-Adapter-FaceID PlusV2双重嵌入技术解析 【免费下载链接】IP-Adapter-FaceID 项目地址: https://ai.gitcode.com/hf_mirrors/h94/IP-Adapter-FaceID 在AI人脸生成领域&#xff0c;如何在保持身份一致性的同时实现风格的灵活控制&#x…...

GitLab实战:如何用rebase -i优雅合并多个commit(附常见错误排查)

Git提交历史优化&#xff1a;交互式rebase高阶操作指南 1. 为什么需要整理Git提交历史 在团队协作开发中&#xff0c;我们经常会遇到提交历史杂乱无章的情况。想象一下这样的场景&#xff1a;你完成了一个新功能的开发&#xff0c;但在这个过程中产生了十几个零散的提交记录&am…...

如何在ComfyUI中玩转WanVideo:从零到一的视频生成魔法

如何在ComfyUI中玩转WanVideo&#xff1a;从零到一的视频生成魔法 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 你是否曾经想过&#xff0c;如果能像搭积木一样轻松创作视频该有多好&#xff…...

RAG实战解析:如何通过检索增强生成提升知识密集型NLP任务性能

1. RAG技术为什么能改变知识密集型NLP任务格局 第一次听说RAG&#xff08;Retrieval-Augmented Generation&#xff09;这个概念时&#xff0c;我正被一个开放域问答项目折磨得焦头烂额。当时我们用纯BART模型生成的答案总是出现事实性错误&#xff0c;比如把"特斯拉创始人…...

别再当黑匣子用了!手把手教你用FastMCP的tool()、resource()和prompt()装饰器,从源码理解到实战避坑

FastMCP装饰器深度解析&#xff1a;从tool()到prompt()的实战进阶指南 1. 为什么需要理解装饰器内部机制&#xff1f; 在Python开发领域&#xff0c;装饰器(Decorator)是一种强大的元编程工具&#xff0c;而FastMCP框架中的tool()、resource()和prompt()装饰器更是将这一理念发…...

SenseVoice语音识别镜像深度体验:自动语言检测+高效推理,实测效果惊艳

SenseVoice语音识别镜像深度体验&#xff1a;自动语言检测高效推理&#xff0c;实测效果惊艳 1. 开箱即用的语音识别体验 当我第一次启动SenseVoice语音识别镜像时&#xff0c;最直观的感受就是"快"。这个基于ONNX量化的多语言语音识别服务&#xff0c;从启动到可用…...

QMCDecode:解放加密音乐的格式转换专家指南

QMCDecode&#xff1a;解放加密音乐的格式转换专家指南 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac&#xff0c;qmc0,qmc3转mp3, mflac,mflac0等转flac)&#xff0c;仅支持macOS&#xff0c;可自动识别到QQ音乐下载目录&#xff0c;默认转换结果存储…...

Pixel Dream Workshop 对比测试:不同采样器与模型版本的出图效果

Pixel Dream Workshop 对比测试&#xff1a;不同采样器与模型版本的出图效果 1. 测试背景与目的 在AI绘画领域&#xff0c;采样器和模型版本的选择直接影响最终生成效果。本次测试旨在通过严谨的对比实验&#xff0c;帮助用户理解Pixel Dream Workshop中不同参数组合的实际表…...

OmenSuperHub终极指南:5分钟掌握惠普游戏本性能优化技巧

OmenSuperHub终极指南&#xff1a;5分钟掌握惠普游戏本性能优化技巧 【免费下载链接】OmenSuperHub 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 厌倦了官方Omen Gaming Hub的臃肿体验&#xff1f;想要一个纯净、高效的硬件控制工具&#xff1f;OmenSup…...