Java Spring AOP代码3分钟快速入手
AOP
Spring入门(十):Spring AOP使用讲解 - 掘金
maven的依赖:
<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId>
</dependency>
<!--aspectj支持-->
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId>
</dependency>
<dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId>
</dependency>
demo1
基于注解实现
AopAnnotation:
package com.example.learn.aop;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AopAnnotation {
}
TestAspect:
package com.example.learn.aop;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
@Slf4j
public class TestAspect {@Pointcut("@annotation(com.example.learn.aop.AopAnnotation)")private void cut() {}@Around("cut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {log.info("====环绕通知start");// 注解所切的方法所在类的全类名String typeName = joinPoint.getTarget().getClass().getName();log.info("目标对象:[{}]", typeName);// 注解所切的方法名String methodName = joinPoint.getSignature().getName();log.info("所切方法名:[{}]", methodName);StringBuilder sb = new StringBuilder();// 获取参数Object[] arguments = joinPoint.getArgs();for (Object argument : arguments) {sb.append(argument.toString());}log.info("所切方法入参:[{}]", sb.toString());// 统计方法执行时间long start = System.currentTimeMillis();//执行目标方法,并获得对应方法的返回值Object result = joinPoint.proceed();log.info("返回结果:[{}]", result);long end = System.currentTimeMillis();log.info("====执行方法共用时:[{}]", (end - start));log.info("====环绕通知之结束");return result;}}
实现一个被织入的类,注意这个类得是Bean,一般aop都是针对容器的,针对普通类的很少且不常用:
AopClass:
package com.example.learn.aop;import org.springframework.stereotype.Component;@Component
public class AopClass {@AopAnnotationpublic void testAop() {System.out.println("func invoked!");}
}
测试:
正是因为AOP是针对Bean的,因此测试的时候不要像下面这样去测试,因为new出来的这个对象没有被Spring管理:
@SpringBootTest
class LearnApplicationTests {@Testvoid contextLoads() {AopClass aopClass = new AopClass();aopClass.testAop();}}
憨憨行为。应该注入容器来测试:
@SpringBootTest
class LearnApplicationTests {@Autowiredprivate AopClass aopClass;@Testvoid contextLoads() {aopClass.testAop();}}
打印结果:
. ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) )' |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot :: (v2.5.5)2023-10-27 10:56:13.600 INFO 16048 --- [ main] com.example.learn.LearnApplicationTests : Starting LearnApplicationTests using Java 1.8.0_381 on DESKTOP-NFN5QCN with PID 16048 (started by DELL in F:\OneDrive\Java学习\yunfei\learn)
2023-10-27 10:56:13.604 INFO 16048 --- [ main] com.example.learn.LearnApplicationTests : No active profile set, falling back to default profiles: default
2023-10-27 10:56:15.202 INFO 16048 --- [ main] com.example.learn.LearnApplicationTests : Started LearnApplicationTests in 1.916 seconds (JVM running for 2.886)
2023-10-27 10:56:15.408 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : ====环绕通知start
2023-10-27 10:56:15.408 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : 目标对象:[com.example.learn.aop.AopClass]
2023-10-27 10:56:15.410 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : 所切方法名:[testAop]
2023-10-27 10:56:15.410 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : 所切方法入参:[]
func invoked!
2023-10-27 10:56:15.420 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : 返回结果:[null]
2023-10-27 10:56:15.420 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : ====执行方法共用时:[10]
2023-10-27 10:56:15.420 INFO 16048 --- [ main] com.example.learn.aop.TestAspect : ====环绕通知之结束
demo2
写一个切面类:
package com.example.base.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;@Aspect
public class Detector {@Pointcut("execution(* com.example.base.AopController.hello(..))")public void helloAspect() {}@Before("helloAspect()")public void beforeAction() {System.out.println("before hello~");}@After("helloAspect()")public void afterAction() {System.out.println("after hello~");}@AfterReturning("helloAspect()")public void afterReturningAction() {System.out.println("after return~");}@Around("helloAspect()")public Object aroundAction(ProceedingJoinPoint pjp) throws Throwable {System.out.println("around~");pjp.proceed();System.out.println("around~");return null;}
}
切点为Controller的一个方法:
package com.example.base;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AopController {@GetMapping("/hello")public String hello(@RequestParam("id") int userId) {return null;}
}
写切面的配置类,自动加载切面:
package com.example.base.aop;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class Config {@Beanpublic Detector detector() {return new Detector();}
}
启动项目,浏览器http://localhost:8080/hello?id=1 触发打印:
2023-09-06 15:49:32.974 INFO 198380 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2023-09-06 15:49:32.974 INFO 198380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2023-09-06 15:49:32.975 INFO 198380 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
around~
before hello~
after return~
after hello~
around~
Disconnected from the target VM, address: '127.0.0.1:61026', transport: 'socket'
相关文章:
Java Spring AOP代码3分钟快速入手
AOP Spring入门(十):Spring AOP使用讲解 - 掘金 maven的依赖: <dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId> </dependency> <!--aspectj支持--> <dependen…...
.NET开源快速、强大、免费的电子表格组件
今天大姚给大家分享一个.NET开源(MIT License)、快速、强大、免费的电子表格组件,支持数据格式、冻结、大纲、公式计算、图表、脚本执行等。兼容 Excel 2007 (.xlsx) 格式,支持WinForm、WPF和Android平台:ReoGrid。 项…...
docker一键部署若依前后端分离版本
比如这里把文件放到/xin/docker/jiaoZ/的目录下,jar包和下面的配置文件都放在这个文件夹下。 注意要把jar端口改为你实际启动的,映射端口也可以改为你想要的。 这里的映射端口为:nginx监听80端口,jar在8620端口,mysq…...
Java项目开发之fastjson详解
Fastjson 是由阿里巴巴公司开发的一个 Java 语言编写的高性能 JSON 处理库。它主要用于 Java 对象与 JSON 数据格式之间的转换,提供了简单易用的 API 来实现序列化(Java 对象转 JSON 字符串)和反序列化(JSON 字符串转 Java 对象&a…...
面试算法-62-盛最多水的容器
题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明:你不能倾斜容器。…...
【智能算法】海洋捕食者算法(MPA)原理及实现
目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2020年,Afshin Faramarzi 等人受到海洋生物适者生存启发,提出了海洋捕食者算法(Marine Predators Algorithm,MPA)。 2.算法原理 2.1算法思想 MPA根据模拟自然界…...
刷题DAY24 | LeetCode 77-组合
1 回溯法理论基础 回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。 所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数。 1.1 回溯法的效率 回溯法的性能如何呢࿰…...
Spring Boot为什么默认使用CGLIB动态代理
兼容性: 1. CGLIB 动态代理可以代理任何类型的目标类,无论它是否实现了接口;[注意的是,类被 final 修饰,那么该不可被继承,即不可被代理;同样,类中 final 修饰的方法&am…...
算法详解——Dijkstra算法
Dijkstra算法的目的是寻找单起点最短路径,其策略是贪心加非负加权队列 一、单起点最短路径问题 单起点最短路径问题:给定一个加权连通图中的特定起点,目标是找出从该起点到图中所有其他顶点的最短路径集合。需要明确的是,这里关心…...
利用GANs进行图像生成
生成对抗网络(GANs)是一种深度学习模型,由两部分组成:生成器(Generator)和判别器(Discriminator)。它们通过相互竞争来提高生成器生成高质量图像的能力。以下是如何利用GANs进行图像…...
Flutter-底部弹出框(Widget层级)
需求 支持底部弹出对话框。支持手势滑动关闭。支持在widget中嵌入引用。支持底部弹出框弹出后不影响其他操作。支持弹出框中内容固定头部和下面列表时,支持触摸头部并在列表不在头部的时候支持滑动关闭 简述 通过上面的需求可知,就是在界面中可以支持…...
聚焦两会:数字化再加速,VR全景助力制造业转型
近年来,随着信息技术、人工智能、VR虚拟现实等新兴技术的不断涌现,数字化正日益成为推动当今经济发展的新驱动力。在不久前的两会上,数字化经济和创新技术再度成为热门话题: 国务院总理李强作政府工作报告: 要深入推…...
数据挖掘之关联规则
“啤酒和尿布的荣誉” 概念 项 item:单个的事物个体 ,I{i1,i2…im}是所有项的集合,|I|m是项的总数项集(item set)/模式(pattern):项的集合,包含k个项的项集称为k-项集数据集(data set)/数据库…...
java:java.util.BitSet对象的Jackson序列化和反序列化实现
java.util.BitSet是个非常方便的比特位数据存储和操作类,一个 bit 具有2个值:0和1,正好可以用来表示 false 和 true,适用于判断“数据是否存在”的场景。 但是,这个从JDK1.0版本就存在的类,Jackson,Fastjso…...
Go语言学习01-基本程序结构
文章目录 Go语言学习01-基本程序结构基本程序结构应用程序入口退出返回值编写测试程序快速设置连续值基本数据类型类型的预定义值指针类型运算符算数运算符比较运算符用 比较数组 逻辑运算符位运算符&^ 按位 置零 Go语言学习01-基本程序结构 基本程序结构 package main …...
rundeck k8s部署踩坑
1、镜像启动后原来的定时任务无法运行 参考: https://github.com/rundeck/rundeck/issues/4275 https://stackoverflow.com/questions/60942785/env-variable-for-rundeck-feature-joblifecycleplugin-enabled/60959605#60959605 结论: (1&…...
每天学习几道面试题|Kafka(二)架构设计类
文章目录 1. Kafka 是如何保证高可用性和容错性的?2. Kafka 的存储机制是怎样的?它是如何处理大量数据的?3. Kafka 如何处理消费者的消费速率低于生产者的生产速率?4. Kafka 集群中的 Controller 是什么?它的作用是什么…...
Spring 实现 OAuth2 授权之解决方案
Spring Security OAuth2 - 已经废弃的项目 早期的Spring 使用 Spring Security OAuth2 实现 OAuth 2.0 的认证服务器和资源服务器。OAuth2是一个授权框架,它允许第三方应用获取有限的访问权限,而无需获取用户的账号和密码等敏感信息。通过这种方式,OAuth2协议实现了安全的用…...
el-select使用filterable下拉无法关闭得问题
这里推荐一个前端框架 sakuya / SCUI,他里面有个formTable,可以解决很多订单明细保存得问题。基本沿用element-plus的前端使用模式,让表单表格变的非常容易。 这个的供应商插件,当使用filterable后,点击表格重的选项&…...
基于javaweb(springboot)城市地名地址信息管理系统设计和实现
基于javaweb(springboot)城市地名地址信息管理系统设计和实现 博主介绍:多年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 央顺技术团队 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
