Spring Aop+自定义注解实践(待完善日志)

目录

前言

1.引入依赖

2.SpringAop的用法举例

3. 自定义注解+AOP的用法举例

3.1 关于Target注解补充

3.2 关于Retention注解补充

3.3 举例


前言

如果你不太理解aop的知识,请看我写的这篇文章,非常详细:

Spring AOP(定义、使用场景、用法、3种事务、事务失效场景及解决办法、面试题)_spring aop的事件-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/m0_64422133/article/details/143376059?spm=1001.2014.3001.5501

1.引入依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.SpringAop的用法举例

service类(获取名字接口)

package com.example.aop_annotation.service;
import org.springframework.stereotype.Service;/*** @author xcw*/
@Service
public class NameService {public String getName(String name){System.out.println("getName方法执行了");return "NameService:"+name;}
}

TestService

这个类实现了 CommandLineRunner类并且重写run(),run()中的操作会在springboot启动后调用

package com.example.aop_annotation.service;import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** @author xcw*/
@Component
public class TestService implements CommandLineRunner {@ResourceNameService nameService;@Overridepublic void run(String... args) throws Exception {nameService.getName("xcw");}
}

切面类:

package com.example.aop_annotation.aop;import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** @author xcw*/
@Aspect
@Component
public class LogAspect {//定义切点拦截NameService类中的所有方法@Pointcut("execution(* com.example.aop_annotation.service.NameService.*(..))")public void pointcut(){}@Before("pointcut()")public void before(JoinPoint joinPoint){Object[] args = joinPoint.getArgs();System.out.println("拦截的类: " + joinPoint.getTarget().getClass().getName());System.out.println("拦截的方法: " + joinPoint.getSignature().getName());System.out.println("方法参数: " + Arrays.toString(args));//方法返回值System.out.println("before前置通知执行了");System.out.println("----------------------------------------------");}@AfterReturning(pointcut = "pointcut()", returning = "result")public void afterReturning(JoinPoint joinPoint, Object result) {System.out.println("拦截的类: " + joinPoint.getTarget().getClass().getName());System.out.println("拦截的方法: " + joinPoint.getSignature().getName());System.out.println("返回值: " + result);System.out.println("afterReturning后置通知执行了");System.out.println("----------------------------------------------");}
}

执行结果如下:

我们把上面代码改为使用自定义注解+AOP的方式

3. 自定义注解+AOP的用法举例

首先我们先创建一个自定义注解类

package com.example.aop_annotation.annotation;import java.lang.annotation.*;/*** @author xcw*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {String value() default "";
}

3.1 关于Target注解补充

@Target:常常配合枚举类ElementType来指定注解的作用位置,即你定义了一个注解,这个注解是类注解还是方法注解还是属性字段注解等具体作用的范围

ElementType的枚举值有

枚举值含义
TYPE类、接口(包括注解类型)、或枚举声明
FIELD字段,包括枚解常量
METHOD方法声明
PARAMETER正式的参数声明
CONSTRUCTOR构造函数的声明
LOCAL_VARIABLE局部变量的声明
ANNOTATION_TYPE注解类型的声明
PACKAGE包声明

3.2 关于Retention注解补充


@Retention:常常配合枚举类RetentionPolicy来指定注解的各种策略,注解的保留时间(生命周期),也就是何时生效,即你定义了一个注解,这个注解是编译时生效还是仅仅只是在代码中标记等等,具体作用的范围,取决于@Retention({RetentionPolic.TYPE})中,RetentionPolic的枚举值,在进行自定义枚举时,大多数都是使用RUNTIME(编译时生效)

RetentionPolic的枚举值

枚举值含义
SOURCE解只在源代码级别保留,编译时被忽略。
CLASS注解将被编译器在类文件中记录,但在运行时不需要JVM保留。这是默认的。
RUNTIME注解将被编译器记录在类文件中,在运行时保留,VM可以读取。一般自定义注解均使用这个。

3.3 举例

我们把上面 2 中的例子改成使用Aop+自定义注解的方式实现

1. 首先我们先创建一个自定义注解类

package com.example.aop_annotation.annotation;import java.lang.annotation.*;/*** @author xcw*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {String value() default "";
}

2. 在方法上使用自定义注解

package com.example.aop_annotation.service;
import com.example.aop_annotation.annotation.MyAnnotation;
import org.springframework.stereotype.Service;/*** @author xcw*/
@Service
public class NameService2 {@MyAnnotationpublic String getName2(String name){System.out.println("getName2方法执行了");return "NameService2:"+name;}
}

3. 把aop切点 指向改为 注解类的包路径

package com.example.aop_annotation.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** @author xcw*/
@Aspect
@Component
public class LogAspect2 {//定义切点拦截使用了自定义注解@MyAnnotation的方法@Pointcut(value = "@annotation(com.example.aop_annotation.annotation.MyAnnotation)")public void pointcut(){}@Before("pointcut()")public void before(JoinPoint joinPoint){Object[] args = joinPoint.getArgs();System.out.println("拦截的类: " + joinPoint.getTarget().getClass().getName());System.out.println("拦截的方法: " + joinPoint.getSignature().getName());System.out.println("方法参数: " + Arrays.toString(args));//方法返回值System.out.println("before前置通知执行了");System.out.println("----------------------------------------------");}@AfterReturning(pointcut = "pointcut()", returning = "result")public void afterReturning(JoinPoint joinPoint, Object result) {System.out.println("拦截的类: " + joinPoint.getTarget().getClass().getName());System.out.println("拦截的方法: " + joinPoint.getSignature().getName());System.out.println("返回值: " + result);System.out.println("afterReturning后置通知执行了");System.out.println("----------------------------------------------");}
}

项目启动后执行的类

package com.example.aop_annotation.service;import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;import javax.annotation.Resource;/*** @author xcw*/
@Component
public class TestService implements CommandLineRunner {@ResourceNameService nameService;@ResourceNameService2 nameService2;@Overridepublic void run(String... args) throws Exception {nameService2.getName2("xcw");}
}

执行结果如下:

后续待完善此文章(AOP+自定义注解+枚举类 实现日志写入打印功能)

如果你也感兴趣可以参考:

springboot aop 自定义注解方式实现完善日志记录(完整源码)-腾讯云开发者社区-腾讯云 (tencent.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/476893.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenCV双目立体视觉重建

本篇文章主要给出使用opencv sgbm重建三维点云的代码&#xff0c;鉴于自身水平所限&#xff0c;如有错误&#xff0c;欢迎批评指正。 环境&#xff1a;vs2015 &#xff0c;opencv3.4.6&#xff0c;pcl1.8.0 原始数据使用D455采集&#xff0c;图像已做完立体校正&#xff0c;如下…

【进阶系列】python简单爬虫实例

python有一个很强大的功能就是爬取网页的信息&#xff0c;这里是CNBlogs 网站&#xff0c;我们将以此网站为实例&#xff0c;爬取指定个页面的大标题内容。代码如下&#xff1a; 首先是导入库&#xff1a; # 导入所需的库 import requests # 用于发送HTTP请求 from bs4 impor…

Ease Monitor 会把基础层,中间件层的监控数据和服务的监控数据打通,从总体的视角提供监控分析

1. 产品定位 Ease Monitor 有如下的产品定位&#xff1a; 关注于整体应用的SLA。 主要从为用户服务的 API 来监控整个系统。 关联指标聚合。 把有关联的系统及其指示聚合展示。主要是三层系统数据&#xff1a;基础层、平台中间件层和应用层。 快速故障定位。 对于现有的系统…

Java学习笔记--数组常见算法:数组翻转,冒泡排序,二分查找

目录 一&#xff0c;数组翻转 二&#xff0c;冒泡排序 三&#xff0c;二分查找&#xff08;一尺之锤&#xff0c;日取其半&#xff0c;万世不竭&#xff09; 一&#xff0c;数组翻转 1.概述:数组对称索引位置上的元素互换&#xff0c;最大值数组序号是数组长度减一 创建跳板…

Python中Tushare(金融数据库)入门详解

文章目录 Python中Tushare&#xff08;金融数据库&#xff09;入门详解一、引言二、安装与注册1、安装Tushare2、注册与获取Token 三、Tushare基本使用1、设置Token2、获取数据2.1、获取股票基础信息2.2、获取交易日历2.3、获取A股日线行情2.4、获取沪股通和深股通成份股2.5、获…

网络编程(JAVA笔记第三十八期)

p.s.这是萌新自己自学总结的笔记&#xff0c;如果想学习得更透彻的话还是请去看大佬的讲解 目录 网络编程概念网络编程三要素IPInetAddress类端口号协议 UDP协议UDP通信程序(发送数据)UDP通信程序(发送数据)使用UDP写聊天室项目UDP的通信方式 TCP协议通过TCP协议实现多发多收通…

Bokeh实现大规模数据可视化的最佳实践

目录 引言 一、Bokeh简介 二、安装Bokeh 三、数据准备 四、性能优化 五、创建图表 六、添加交互功能 七、应用案例 八、高级技巧 九、总结 引言 在数据科学领域,数据可视化是一个至关重要的环节。通过可视化,我们可以直观地理解数据的特征和趋势,为数据分析和决策…

IDEA2023 SpringBoot整合MyBatis(三)

一、数据库表 CREATE TABLE students (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(100) NOT NULL,age INT,gender ENUM(Male, Female, Other),email VARCHAR(100) UNIQUE,phone_number VARCHAR(20),address VARCHAR(255),date_of_birth DATE,enrollment_date DATE,cours…

PVE的优化与温度监控(二)—无法识别移动硬盘S.M.A.R.T信息的思考并解决

前情提要&#xff1a;空闲2.5英寸机械硬盘&#xff0c;直接放到PVE上测试NAS 使用&#xff0c;通过SATA线的方式让小主机不太美观&#xff0c;并且失去了前期调试的安全性。购入移动硬盘盒&#xff0c;缺点&#xff0c;USB 连接&#xff0c;会失去一些特性。比如本文中遇到的问…

记录下jekins新建个前端部署配置项

1 新建个item 2 输入项目名称&#xff0c;选择个新的工程或 或者搜个已存在的现有模板 3 添加一些描述 4 &#xff08;可选&#xff09;配置下构建历史保存情况 5 限制下构建节点和选择gitlab或者github 6 写下git仓库地址、账号密码以及分支 7 选择构建工具node以及版本 8 构建…

文件管理 II(文件的物理结构、存储空间管理)

一、文件的物理结构 文件实际上是一种抽象数据类型&#xff0c;我们要研究它的逻辑结构、物理结构&#xff0c;以及关于它的一系列操作。文件的物理结构就是研究文件的实现&#xff0c;即文件数据在物理存储设备上是如何分布和组织的。同一个问题有两个方面的回答&#xff1a;…

大数据新视界 -- 大数据大厂之 Impala 性能优化:跨数据中心环境下的挑战与对策(上)(27 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

利用 GitHub 和 Hexo 搭建个人博客【保姆教程】

利用 GitHub 和 Hexo 搭建个人博客 利用 GitHub 和 Hexo 搭建个人博客一、前言二、准备工作&#xff08;一&#xff09;安装 Node.js 和 Git&#xff08;二&#xff09;注册 GitHub 账号 三、安装 Hexo&#xff08;一&#xff09;创建博客目录&#xff08;二&#xff09;安装 H…

ABAP开发-CO的底层表-物料价格分析CKM3

系列文章目录 文章目录 系列文章目录[TOC](文章目录) 前言一、物料分类账与CKM3二、CKM3界面分析三、CKM3的主要功能1、物料价格分析2、成本构成分析3、价格差异分析4、期间状态查看 四、物料分类账与CKM3的关系五、CKM3的底层表及数据支持1、核心数据表2、取数逻辑 总结 前言 …

汽车被追尾了怎么办?

今天开车上班的路上发生了一起4车追尾的交通事故&#xff0c;作为过来人我复盘了下交通追尾的处理过程。简述如下&#xff1a; 发生追尾后打双闪及时放置三角架&#xff0c;提醒后面车这里发生交通事故了 打122交警电话和自行拍下事故现场的远近照片。如果车子损伤严重或事故复…

了解Redis(第一篇)

目录 Redis基础 什么事Redis Redis为什么这么快 除了 Redis&#xff0c;你还知道其他分布式缓存方案吗? 说-下 Redis 和 Memcached 的区别和共同点 为什么要用Redis? 什么是 Redis Module?有什么用? Redis基础 什么事Redis Redis &#xff08;REmote DIctionary S…

javascrip页面交互

元素的三大系列 offset系列 offset初相识 offset系列属性 作用 element.offsetParent 返回作为该元素带有定位的父级元素&#xff0c;如果父级没有定位&#xff0c;则返回body element.offsetTop 返回元素相对于有定位父元素上方的偏移量 element.offsetLeft 返回元素…

K8S + Jenkins 做CICD

前言 这里会做整体CICD的思路和流程的介绍&#xff0c;会给出核心的Jenkins pipeline脚本&#xff0c;最后会演示一下 实验/实操 结果 由于整体内容较多&#xff0c;所以不打算在这里做每一步的详细演示 - 本文仅作自己的实操记录和日后回顾用 要看保姆式教学的可以划走了&…

nvm安装node遇到的若干问题(vscode找不到npm文件、环境变量配置混乱、npm安装包到D盘)

问题一&#xff1a;安装完nvm后需要做哪些环境变量的配置&#xff1f; 1.打开nvm文件夹下的setting文件&#xff0c;设置nvm路径和安装node路径&#xff0c;并添加镜像。 root: D:\software\nvm-node\nvm path: D:\software\nvm-node\nodejs node_mirror: https://npmmirror.c…

shell脚本(五)

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…