Spring Boo项目中方法参数对象中字段上存在的自定义注解如何进行拦截解析

一、前言

在Spring Boot项目开发过程中,我们经常会使用到自定义注解的方式进行业务逻辑开发,此时注解我们一般是放在方法或者类上面,通过AOP切面拦截的方式进行自定义业务逻辑填充。但是如果自定义注解放在类的字段上,此时应该如何进行解析呢?

二、技术思路

自定义注解放在类的字段上其实解析起来也是比较容易的,我这里采用的思路是:

自定义一个MethodInterceptor拦截器拦截执行的业务方法,获取到方法参数数组,遍历每个参数,获取每个参数中所有字段,判断字段上是否有自定义注解,筛选出所有标识了自定义注解的字段,然后进行自定义业务逻辑填充。

三、技术实践

按照上面的思路,我们进行一下技术实践,这里我模拟一个案例。

1. 需求

自定义一个注解,该注解作用于类的字段上,带有该标识注解的字段,在使用时,如果字段没有设置值,则采用注解设置的默认值。

2. 新建spring boot项目,导入相关依赖

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

3. 自定义注解

示例代码如下:

import java.lang.annotation.*;@Target({ElementType.FIELD}) // 标识此注解适用于字段上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DefaultValueAnnotation {String value() default "";
}

4. 字段注解获取工具类

示例代码:

import lombok.Data;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.ReflectionUtils;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;/*** 字段上注解查找工具类*/
public class FieldAnnotationUtils {/*** 字段注解信息返回VO*/@Datapublic static class FieldAnnotationInfo {/*** 类变量*/private Object obj;/*** 携带该注解的字段对象*/private Field field;/*** 注解对象*/private Annotation annotation;}/*** 判断类变量中是否字段上存在指定的注解,如果存在,则返回字段和注解信息** @param obj            类变量* @param annotationType 注解类型* @return*/public static List<FieldAnnotationInfo> parseFieldAnnotationInfo(Object obj, Class annotationType) {return parseFieldAnnotationInfo(obj, annotationType, null);}/*** 判断类变量中是否字段上存在指定的注解,如果存在,则返回字段和注解信息** @param obj              类变量* @param annotationType   注解类型* @param filterFieldClazz 注解适用的字段类型(不适用的字段类型即使字段上面添加改注解也不生效)* @return*/public static List<FieldAnnotationInfo> parseFieldAnnotationInfo(Object obj, Class annotationType, Set<Class> filterFieldClazz) {if (obj == null) {return null;}List<FieldAnnotationInfo> resultList = new ArrayList<>();/*** 获取该对象的所有字段,进行遍历判断*/ReflectionUtils.doWithFields(obj.getClass(), field -> {// 判断该字段上是否存在注解Annotation annotation = AnnotatedElementUtils.findMergedAnnotation(field, annotationType);if (annotation != null) { // 如果存在指定注解boolean flag = true;if (filterFieldClazz != null && !filterFieldClazz.isEmpty()) { // 如果指定了适用的字段的类型for (Class c : filterFieldClazz) {if (c.isAssignableFrom(field.getType())) { // 判断该字段类型是否符合使用类型,使用isAssignableFrom方法是为了父类也进行判断break;}flag = false;}}if (flag) { // 如果该字段类型符合,则返回字段注解信息FieldAnnotationInfo fieldAnnotationInfo = new FieldAnnotationInfo();fieldAnnotationInfo.setObj(obj);fieldAnnotationInfo.setField(field);fieldAnnotationInfo.setAnnotation(annotation);resultList.add(fieldAnnotationInfo);}}});return resultList;}
}

5. 自定义MethodInterceptor

示例代码:

public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {// 获取执行方法的所有参数Object[] arguments = invocation.getArguments();// 参数列表不为空if (arguments != null && arguments.length != 0) {// 由于我这里注解定义简单,我只让String类型的字段生效Set<Class> clazzSet = new HashSet<>();clazzSet.add(CharSequence.class);for (int i = 0; i < arguments.length; i++) { // 判断所有参数// 从每个参数中获取字段上有@DefaultValueAnnotation注解标识,并且类型是CharSequence的字段信息List<FieldAnnotationUtils.FieldAnnotationInfo> fieldAnnotationInfos = FieldAnnotationUtils.parseFieldAnnotationInfo(arguments[i], DefaultValueAnnotation.class, clazzSet);if (!CollectionUtils.isEmpty(fieldAnnotationInfos)) { // 如果存在符合条件的字段信息for (int m = 0; m < fieldAnnotationInfos.size(); m++) { // 判断所有符合条件的字段FieldAnnotationUtils.FieldAnnotationInfo fni = fieldAnnotationInfos.get(m);Field field = fni.getField(); // 获取字段field.setAccessible(true); // 设置可访问,突破private权限Object value = field.get(fni.getObj());if (value == null) { // 判断当前字段是否已经有值// 如果当前字段没有值,利用反射的方式,把注解中的值设置进去field.set(fni.getObj(), ((DefaultValueAnnotation) fni.getAnnotation()).value());}field.setAccessible(false);}}}}// 放行方法执行return invocation.proceed();}
}

6. 把自定义的MethodInterceptor织入到Spring容器中

示例代码:

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyInterceptorConfig {@Beanpublic DefaultPointcutAdvisor DefaultPointcutAdvisor() {DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();defaultPointcutAdvisor.setAdvice(new MyMethodInterceptor()); // 自定义MethodInterceptorAspectJExpressionPointcut aspectJExpressionPointcut = new AspectJExpressionPointcut();aspectJExpressionPointcut.setExpression("execution(* com.learn..*(..))"); // 指定需要拦截的切面defaultPointcutAdvisor.setPointcut(aspectJExpressionPointcut);return defaultPointcutAdvisor;}}

7. 使用自定义注解

示例代码:

import lombok.Data;@Data
public class TestParamPojo {@DefaultValueAnnotation("我是注解设置的值.")private String name;@DefaultValueAnnotation("100")private Integer age;
}

8. 定义方法入参

示例代码:

@Component
public class TestService {public void test() {System.out.println("test empty...");}public void test(TestParamPojo pojo) {System.out.println("test pojo: " + pojo.toString());}public void test(TestParamPojo pojo, String testStr) {System.out.println("test pojo: " + pojo.toString() + " testStr: " + testStr);}}

9.测试

  • 测试代码:

        @Autowiredprivate TestService testService;@PostConstructpublic void init() {System.out.println("=========================");testService.test();TestParamPojo testParamPojo = new TestParamPojo();testService.test(testParamPojo);testService.test(testParamPojo, null);testParamPojo.setName("我是自己设置的...");testService.test(testParamPojo, "hello, world.");System.out.println("=========================");}
    
  • 测试结果:

    在这里插入图片描述

  • 测试结论

    可以看到,在没有设置值的时候,可以从注解中获取默认值进行设置,同时,不是指定的字段类型即使标识了自定义注解也不会生效。

四、写在最后

本文是对Spring Boo项目中方法参数对象中字段上存在的注解如何进行拦截解析的技术探讨,以上只是技术思路的一种实现方式,仅供大家参考。

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

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

相关文章

短链接的背后故事:为互联网用户带来的便捷与安全

title: 短链接的背后故事&#xff1a;为互联网用户带来的便捷与安全 date: 2024/2/26 14:58:58 updated: 2024/2/26 14:58:58 tags: 短链接技术起源长URL问题解决链接分享便利性链接跟踪与分析链接管理效率提升链接安全保障应用领域广泛 一、短链接的起源 短链接是一种将长UR…

精益生产,创新驱动:机器人技术引领企业的未来之路

随着自动化技术的普及和物联网、人工智能技术的迅速发展&#xff0c;全球制造业正在经历着一场革命性的变革。传统以人力劳动为基础的制造业正逐渐向以机器为主导的智能生产模式转型。企业们正积极探索更高效的制造方式&#xff0c;通过新兴技术提升生产力&#xff0c;同时降低…

【BUG 记录】MyBatis-Plus 处理枚举字段和 JSON 字段

【BUG 记录】MyBatis-Plus 处理枚举字段和JSON字段 一、枚举字段&#xff08;mysql环境已测、postgresql环境已测&#xff09;1.1 场景1.2 定义枚举常量1.3 配置枚举处理器1.4 测试 二、JSON字段&#xff08;mysql环境已测&#xff09;2.1 导包2.2 使用对象接受2.3 测试 三、JS…

[玩转AIGC]LangChain文本分词器

LangChain提供了多种不同类型的文本分词器&#xff0c;我们常说的tokenizer就是分词器的一种。 我们知道对于LLaMA与LLaMA2的文本分词器为基于sentencepiece的BPE模型&#xff0c;Google &#xff0c;而openai的文本分词器为tiktoken&#xff0c;据openai官方介绍&#xff0c;t…

【Redis学习笔记03】Java客户端

1. 初识Jedis Jedis的官网地址&#xff1a;https://github.com/redis/jedis 1.1 快速入门 使用步骤&#xff1a; 注意&#xff1a;如果是云服务器用户使用redis需要先配置防火墙&#xff01; 引入maven依赖 <dependencies><!-- 引入Jedis依赖 --><dependency&g…

Apache DolphinScheduler 3.2.1 版本发布:增强功能与安全性的全面升级

近期&#xff0c;Apache DolphinScheduler 社区激动地宣布 3.2.1 版本的发布。此次更新不仅着力解决了前一版本&#xff08;3.2.0&#xff09;中遗留的问题&#xff0c;而且引入了一系列的功能增强和优化措施。 原先的问题主要源于部分重要代码在发布过程中未能成功合并&#x…

防御保护第八、九、十、十一天笔记

一、内容安全 1、DFI和DPI技术 --- 深度检测技术 DPI是一种基于应用层的流量检测和控制技术&#xff0c;它会对流量进行拆包&#xff0c;分析包头和应用层的内容&#xff0c;从而识别应用程序和应用程序的内容。这种技术增加了对应用层的分析&#xff0c;识别各种应用&#xf…

Learning to Branch for Multi-Task Learning

activations bent 辅助信息 作者未提供代码

4.4 MySQL存储

目录 1、使用前提 2、使用连接数据库最初步骤 2.1 最初步骤 2.2 connect()方法中参数简单传递 3、创建数据库(创建架构)和创建表 3.1 创建数据库(创建架构) 3.2 创建表 3.2.1 基本创建 3.2.2 创建自增主键 4、Pycharm 可视化连接 MySQL 图形界面 5、插入、更新、查询…

云HIS支持连锁集团化管理,1+N模式,支撑运营,管理,决策多位一体

目录 云HIS系统特色 使用简易化 连锁集团化 可扩展化 系统描述 云HIS系统优势 &#xff08;1&#xff09;客户/用户角度 &#xff08;2&#xff09;开发/运维角度 &#xff08;3&#xff09;成功应用案例 HIS分系统&#xff08;HIS子系统&#xff09; 1、医疗业务子…

回归预测 | Matlab实现CPO-HKELM冠豪猪算法优化混合核极限学习机多变量回归预测

回归预测 | Matlab实现CPO-HKELM冠豪猪算法优化混合核极限学习机多变量回归预测 目录 回归预测 | Matlab实现CPO-HKELM冠豪猪算法优化混合核极限学习机多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-HKELM冠豪猪算法优化混合核极限学习机…

高频面试题整理(二)

文章目录 索引相关问题优化你的索引 密集索引和稀疏索引如何定位并优化慢查询sqlMyISAM与InnoDB 关于锁方面的区别是什么&#xff1f;MyISAMInnoDB事务隔离级别 多线程并发的相关问题Thread中的start和run方法的区别Thread和Runnable是什么关系&#xff1f;如何处理线程的返回值…