spring-core:获取类/方法/字段/字段上直接定义的注解

AnnotatedElement.getAnnotation

如何获取一个类上定义的注解?
这个问题似乎不应该问,我们知道如果要获取一个类/方法/字段/字段上直接定义的注解是很方便的,如Class.getAnnotation(Class<CasbanScan>)就能实现,
只要实现了java.lang.reflect.AnnotatedElement接口的对象(Class,Method,Field)都有这个方法,
但是在Spring框架下,如果注解中有@AliasFor定义了别名的字段,要区别对待。
如下示例,
Class.getAnnotation获取注解对象,basePackages字段是空的,value字段才能获取正确的值。

	@Testpublic void test2GetDirectlyAnnotation() {try {{System.out.printf("-----> For %s\n",UserSummy.class.getSimpleName());System.out.println("\t==== USING Class.getAnnotation ====");CasbanScan annot = UserSummy.class.getAnnotation(CasbanScan.class);System.out.println("\t"+annot.toString());assertArrayEquals(new String[] {"hello"}, annot.value());System.out.printf("\tvalue() size:%d\n",annot.value().length);System.out.printf("\tbasePackages() size:%d\n",annot.basePackages().length);assertEquals(0, annot.basePackages().length);}} catch (Throwable e) {e.printStackTrace();fail();}}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface CasbanScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};}@CasbanScan("hello")public static class UserSummy{}

Spring框架将注解(Annotation)用到了极致,对注解定义扩展了很多灵活了定义,@AliasFor就是一种灵活扩展。所以在Spring框架下,要获取正确直接定义在类上的注解。Class.getAnnotation(Class<CasbanScan>)方法并不一定合适。

Spring-core

SearchStrategy

为适应各种场景,Spring通过枚举类型SearchStrategy来定义搜索策略,
其中SearchStrategy.DIRECT 定义为仅查找直接声明的注释,而不考虑@Inherited注释,也不搜索父类或实现的接口。
所以只要使用SearchStrategy.DIRECT 作为搜索策略就只查找直接声明的注释。

MergedAnnotations

MergedAnnotations.from(AnnotatedElement element)方法就是使用SearchStrategy.DIRECT 作为搜索策略 创建一个新的MergedAnnotations实例,其中包含来自指定元素的所有注释和元注释
如下是MergedAnnotations.from(AnnotatedElement element)方法的实现

	static MergedAnnotations from(AnnotatedElement element) {return from(element, SearchStrategy.DIRECT);}

所以我们可以使用MergedAnnotations.from(AnnotatedElement element)方法来获取直接注解定义,

MergedAnnotation<CasbanScan> mergedAnnotation = MergedAnnotations.from(UserSummy.class).get(CasbanScan.class);
if(mergedAnnotation.isDirectlyPresent()){System.out.println("FOUND @CasbanScan in UserSummy");/** 将 MergedAnnotation转为方便输出的 AnnotationAttributes 对象 */System.out.println(mergedAnnotation.asAnnotationAttributes());/** 直接从MergedAnnotation对象读取字段 */System.out.println(mergedAnnotation.getStringArray("basePackages")[0]);System.out.println(mergedAnnotation.getStringArray("value")[0]);
}

完整测试代码如下:

import static org.junit.Assert.*;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.Test;import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;public class SpringAnnotationUtilsTest {@Testpublic void test2GetDirectlyAnnotation() {try {System.out.printf("-----> For %s\n",UserSummy.class.getSimpleName());{/*** 直接调用 Class.getAnnotation方法可以读取到注解,但对于用@AliasFor定义了别名的字段,要区别对待。* 如下,basePackages字段是空的,value字段才能获取正确的值 */System.out.println("\t==== USING Class.getAnnotation ====");CasbanScan annot = UserSummy.class.getAnnotation(CasbanScan.class);System.out.println("\t"+annot.toString());assertArrayEquals(new String[] {"hello"}, annot.value());System.out.printf("\tvalue() size:%d\n",annot.value().length);System.out.printf("\tbasePackages() size:%d\n",annot.basePackages().length);assertEquals(0, annot.basePackages().length);}{System.out.println("\t==== USING AnnotationUtils.isAnnotationDeclaredLocally  ====");boolean declaredLocally = AnnotationUtils.isAnnotationDeclaredLocally(CasbanScan.class, UserSummy.class);System.out.printf("\t@%s declaredLocally in %s:%b\n",CasbanScan.class.getSimpleName(),UserSummy.class.getSimpleName(), declaredLocally);assertTrue(declaredLocally);System.out.println("\t==== USING Spring ====");MergedAnnotations mergedAnnotations= MergedAnnotations.from(UserSummy.class);assertTrue(mergedAnnotations.isDirectlyPresent(CasbanScan.class));MergedAnnotation<CasbanScan> mergedAnnotation= mergedAnnotations.get(CasbanScan.class);assertTrue(mergedAnnotation.isDirectlyPresent());/** 将 MergedAnnotation转为方便输出的 AnnotationAttributes 对象 */System.out.println("\t"+mergedAnnotation.asAnnotationAttributes());/** 直接从MergedAnnotation对象读取字段 */assertArrayEquals(new String[] {"hello"}, mergedAnnotation.getStringArray("basePackages"));assertArrayEquals(new String[] {"hello"}, mergedAnnotation.getStringArray("value"));System.out.println("\t==== USING Annotation synthesized ====");/*** 获取合成注解对象 */CasbanScan annot = mergedAnnotation.synthesize();/** 调用AnnotationUtils.getAnnotationAttributes将 Annotation对象转为方便输出的Map  */System.out.printf("\t%s\n", AnnotationUtils.getAnnotationAttributes(annot));/** 对于用@AliasFor定义了别名的字段不论用读取哪个字段都是有正确的值*/assertArrayEquals(new String[] {"hello"}, annot.value());assertArrayEquals(new String[] {"hello"}, annot.basePackages());}{System.out.printf("-----> For %s\n",VipSummy.class.getSimpleName());MergedAnnotations mergedAnnotations= MergedAnnotations.from(VipSummy.class);boolean declaredLocally = mergedAnnotations.isDirectlyPresent(CasbanScan.class);System.out.printf("\t%s FOUND directly @%s in %s\n", declaredLocally?"":"NOT",CasbanScan.class.getSimpleName(),VipSummy.class.getSimpleName());assertFalse(mergedAnnotations.isDirectlyPresent(CasbanScan.class));MergedAnnotation<CasbanScan> mergedAnnotation= mergedAnnotations.get(CasbanScan.class);assertFalse(mergedAnnotation.isDirectlyPresent());}} catch (Throwable e) {e.printStackTrace();fail();}}@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface CasbanScan {@AliasFor("basePackages")String[] value() default {};@AliasFor("value")String[] basePackages() default {};}@CasbanScan("hello")public static class UserSummy{}public static class VipSummy extends UserSummy{}
}

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

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

相关文章

Linux:Win10平台上,用VMware安装Centos7.x及系统初始化关键的相关配置(分步骤操作,详细,一篇足以)

VMware安装Centos7.x镜像的详细步骤&#xff1a;VMWare安装Centos系统&#xff08;无桌面模式&#xff09; 我这里是为了安装Hadoop集群&#xff0c;所以&#xff0c;以下这些步骤是必须进行的 如果你是学习Linux&#xff0c;可以跳过非必须的那些配置项 我安装的版本是&…

集群工具之HAProxy

集群工具之HAProxy HAProxy简介 它是一款实现负载均衡的调度器适用于负载特别大的web站点HAProxy的工作模式 mode http&#xff1a;只适用于web服务mode tcp&#xff1a;适用于各种服务mode health&#xff1a;仅做健康检查&#xff0c;很少使用 配置HAProxy client&#x…

jmeter--取样器-- HTTP请求

HTTP请求&#xff08;HTTP Request&#xff09; 右键 >>> 添加 >>> 取样器 >>> HTTP请求&#xff08;HTTP Request&#xff09;基本web服务器协议&#xff1a;https服务器名称或IP&#xff1a;端口号&#xff1a;443HTTP请求请求方式&#xff1a;路…

基于JAVA的机场航班起降与协调管理系统

毕业设计&#xff08;论文&#xff09;任务书 第1页 毕业设计&#xff08;论文&#xff09;题目&#xff1a; 基于JAVA的机场航班起降与协调管理系统 毕业设计&#xff08;论文&#xff09;要求及原始数据&#xff08;资料&#xff09;&#xff1a; 1&#xff0e;综述机场航班调…

【java配置】jpcap的下载与idea配置

解决报错&#xff1a;Cannot resolve symbol ‘jpcap’ 1. jpcap的下载 官网下载链接 百度网盘下载 双击WinpPca安装&#xff0c;jacap1和jpcap2任选其中之一 2. idea配置 &#xff08;1&#xff09;查看当前使用jdk目录 File -> Project Settings -> SDKs &#…

【1577】java网吧收费管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 网吧收费管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

项目实践---贪吃蛇小游戏(下)

对于贪吃蛇小游戏&#xff0c;最主要的还是主函数部分&#xff0c;这里就和大家一一列举出来&#xff0c;上一章已经写过头文件了&#xff0c;这里就不多介绍了。 首先就是打印桌面&#xff0c;也就是背景&#xff0c;则对应的代码为&#xff1a; void SetPos(short x, short …

查看 Oracle 表空间的使用情况

查看 Oracle 表空间的使用情况 一、查看表空间信息 SQL> select tablespace_name,file_name,user_bytes/1024/1024 sizeMB from dba_data_files order by tablespace_name;TABLESPACE_NAME FILE_NAME SIZEMB -------------------------…

MLLM | Mini-Gemini: 挖掘多模态视觉语言大模型的潜力

香港中文、SmartMore 论文标题&#xff1a;Mini-Gemini: Mining the Potential of Multi-modality Vision Language Models Code and models are available at https://github.com/dvlab-research/MiniGemini 一、问题提出 通过更高分辨率的图像增加视觉标记的数量可以丰富…

Power BI 如何创建页面导航器?(添加目录按钮/切换页面按钮)

Power BI 中页导航是什么&#xff1f; 在Power BI中&#xff0c;页导航&#xff08;Page Navigation&#xff09;是指在报告中创建多个页面&#xff08;页&#xff09;&#xff0c;然后允许用户在这些页面之间进行导航的功能。 如下图所示&#xff0c;页导航的选项和报告中的…

嵌入式学习59-ARM8(中断,ADC,内核定时器和传感器)

什么是中断顶半部和底半部 &#xff1f; &#xff08;部分记忆&#xff09;背 上半部&#xff1a; …

计算机中浮点数的表示以及计算

网上关于这个问题的基础内容有很多文章了&#xff0c;比如&#xff1a;计算机组成原理_浮点数的表示与运算_浮点数左规右规是算术移位-CSDN博客 计算机系统基础&#xff1a;浮点数的表示 - 知乎 【计算机组成原理】1、浮点数的二进制表示、科学计数法、IEEE754标准_浮点数二进…

Atlas Vector Search:借助语义搜索和 AI 针对任何类型的数据构建智能应用

Atlas Vector Search已正式上线&#xff01; Vector Search&#xff08;向量搜索&#xff09;现在支持生产工作负载&#xff0c;开发者可以继续构建由语义搜索和生成式人工智能驱动的智能应用&#xff0c;同时通过 Search Node&#xff08;搜索节点&#xff09;优化资源消耗并…

Vue 2与Vue 3生命周期钩子的对比分析

一、概述 Vue 组件实例在创建时经历一系列初始化步骤&#xff0c;Vue 在合适的时机调用特定函数&#xff0c;允许开发者在特定阶段运行自己的代码&#xff0c;这些函数称为生命周期钩子。 二、规律 生命周期可分为四个阶段&#xff1a;创建、挂载、更新、销毁&#xff0c;每…

一些网络的常见问题

1. tcp和udp可以同时监听相同端口号吗&#xff1f; 答&#xff1a;可以。IP数据包首部有个叫协议字段&#xff0c;指出了上层协议是TCP还是UDP。 网络层读取数据包的时候&#xff0c;已经知道上层是什么报文&#xff0c;可以直接交给内核进程做区分处理。 2. 多个线程可以使用…

SpringCloud系列(12)--服务提供者(Service Provider)集群搭建

前言&#xff1a;在上一章节中我们成功把微服务注册进了Eureka集群&#xff0c;但这还不够&#xff0c;虽然注册服务中心Eureka已经是服务配置了&#xff0c;但服务提供者目前只有一个&#xff0c;如果服务提供者宕机了或者流量过大&#xff0c;都会影响到用户即服务使用者的使…

Java-GUI-AWT-布局

1 需求 Frame&#xff1a;默认布局是BorderLayoutDialog&#xff1a;默认布局是BorderLayoutPanel&#xff1a;默认布局是FlowLayout 2 接口 3 示例 在Java AWT&#xff08;Abstract Window Toolkit&#xff09;中&#xff0c;各种容器的默认布局方式如下&#xff1a; Frame…

【刷爆LeetCode_01题_合并两个有序数组】

算法题&#xff0c;好像是不让使用函数 一、题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。…

Oracle数据库的简单使用

Oracle简单使用 一、数据库的介绍二、Oracle介绍账号管理Oracle的安装Oracle服务的作用OracleRemExecService服务创建数据库 常用命令 三、SQL语言SQL分类实用的数据表添加注释数据操纵语言&#xff08;DML&#xff09;查询语句&#xff08;SELECT&#xff09;wherelikedistinc…

pycharm集成github项目,拉取项目并进行代码管理

首先你要有一个github项目&#xff0c;然后找到一个想要拉取github项目的本地路径&#xff0c;打开git命令行&#xff0c;执行git clone http…路径&#xff0c;可能会需要你输入git的用户名和密码&#xff1b;用pycharm打开该项目&#xff1b;添加python解释器&#xff0c;我用…