Spring注解之自定义注解入门
前言
在业务开发过程中,Spring 框架自带的注解并非总能满足形形色色的业务需求,所以我们需要自定义注解来满足特定需求。在定义自己的注解之前,我们先探讨自定义注解的入门知识——Spring为我们提供的元注解和定义注解的基本语法。
注解是什么
Spring 官方文档对 注解(annotation) 的定义如下:
An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.
中文意思就是:
注解是一种元数据,可以添加到Java源代码中。 类、方法、变量、参数和包都可以被注解。 注解对被注解代码的操作没有直接影响。
通过官方描述,可以提炼出如下三条关键信息:
- 注解是一种元数据。即注解是属于java的一种数据类型,与类、接口和数组等类似;
- 注解用来修饰类、方法、变量、参数和包等;
- 注解不会对所修饰的代码产生直接的影响。
自定义注解
使用关键字@interface定义自己的注解时,自动继承java.lang.annotation.Annotation接口,由编译程序完成其它细节。在定义注解时,不能继承其它的注解或接口,其内部只能定义注解类型元素(annotation type element),可以通过default来声明注解类型元素的默认值。
注解定义基本语法:
public @interface 注解名
通俗地讲,注解类型元素可以视作类的成员变量,故本文不作严格区分;其支持的数据类型包括:
- 所有基本数据类型(int,float,boolean,byte,double,char,long,short)
- String类型
- Class类型
- enum类型
- Annotation类型
- 以上所有类型的数组
Annotation类型里面的成员变量该怎么设定?
第一,只能设置public或默认(default)这两种访问权限修饰符。例如,String value(); 设为defaul默认类型。
第二,参数类型只能用八种基本数据类型byte,short,char,int,long,float,double,boolean和 String,Enum,Class,annotations等数据类型,以及这一些类型的数组。例如,String value();这里的参数类型就是String。
第三,成员变量一般定义为名词。
第四,如果只有一个成员变量,建议将其命名为Spring默认的 “value()”。
简单的自定义注解示例:
package com.eg.wiener.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定义画图注解
*
* @author Wiener
* @date 2021/1/30
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ShapeAn {
String value();
String beanName() default "circle";
}
成员变量的定义与接口中定义抽象方法的语法高度类似,但是,这里可以设定默认值。因此注解类型元素的语法规范不走寻常路,即有属性的特征——可以赋值,又有方法的特征——打上了一对小括号。
可以通过在注解中使用属性来配置一些参数,然后使用反射获取这些参数,这些注解没有其他特殊的功能,只是简单的代替xml配置的方式来配置一些参数。使用注解来配置参数这在Springboot中得到了热捧,如@Configuration。关于注解的详细使用,请移步《》。
元注解
元注解的作用就是注解其它注解,即用来说明其它 annotation类型。Java5.0在包java.lang.annotation中定义了4个标准的meta-annotation,分别是 @Target、@Retention、@Documented和@Inherited,其中,前两个比较常见。下面我们看一下每个元注解的作用和相应参数的使用说明。
@Target
@Target说明了Annotation所修饰的对象范围,默认可以在任何地方使用,也可以指定使用的范围。无规矩不成方圆,约定好规则,防止因乱用而出现稀奇古怪的问题。
其属性通过ElemenetType类定义,可用的枚举值见下表:
枚举值 | 功能 | 示例 |
---|---|---|
CONSTRUCTOR | 用于描述构造器 | |
FIELD | 用于描述域/属性(包括 enum 实例) | @Autowired |
LOCAL_VARIABLE | 用于描述局部变量 | |
METHOD | 用于描述方法 | @RequestMapping |
PACKAGE | 用于描述包 | |
PARAMETER | 用于描述参数 | @RequestParam |
TYPE | 用于描述类、接口(包括注解类型) 或enum声明 | @Controller |
@Retention
@Retention定义了该Annotation的生命周期,表示需要在什么级别保存该注解信息,即:被描述的注解在什么范围内有效。
元注解 Retention 有唯一的value作为成员变量,它的取值以枚举值的形式定义在java.lang.annotation.RetentionPolicy中,可选参数包括:
SOURCE:源码级别,在源文件中有效。注解只存在于源码中,一般用于和编译器交互,在编译阶段检测代码。如@Override和@SuppressWarings等。
CLASS:字节码级别,在class文件中有效。即注解存在于源码和字节码文件中,主要用于编译时生成额外的文件,如XML,Java文件等,但运行时无法获得。 如mybatis生成实体和映射文件,这个级别需要添加JVM加载时候的代理(javaagent),使用代理来动态修改字节码文件。
RUNTIME:运行时级别,注解存在于源码、字节码和java虚拟机中。在运行时有效,注解处理器此时可以通过反射技术获取到此注解的属性值,从而去做一些运行时的业务逻辑处理。
实际业务开发中,自定义注解生命周期几乎都是采用RUNTIME。
@Documented
@Documented用于描述自定义的注解应该作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员变量。
@Inherited
元注解@Inherited 是一个标记注解,她阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的注解类型被用于一个class,则这个annotation将同时被用于该class的子类。@Inherited注解只对那些@Target被定义为ElementType.TYPE的自定义注解起作用。
结束语
老铁们,因楼兰胡杨能力有限,文中难免出现瑕疵,如果发现bug或者有更好的idea,请在文章下方留言!
Reference
- https://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
- https://zhuanlan.zhihu.com/p/288328296
- https://segmentfault.com/a/1190000013258647
- https://www.cnblogs.com/anyiz/p/10605401.html
Spring注解之自定义注解入门的更多相关文章
- Java注解-元数据、注解分类、内置注解和自定义注解|乐字节
大家好,我是乐字节的小乐,上次说过了Java多态的6大特性|乐字节,接下来我们来看看Java编程里的注解. Java注解有以下几个知识点: 元数据 注解的分类 内置注解 自定义注解 注解处理器 Ser ...
- Java中的注解及自定义注解你用的怎么样,能不能像我这样应用自如?
Java注解提供了关于代码的一些信息,但并不直接作用于它所注解的代码内容.在这个教程当中,我们将学习Java的注解,如何定制注解,注解的使用以及如何通过反射解析注解. Java1.5引入了注解,当前许 ...
- Springboot--元注解及自定义注解(表单验证)
本文简单说明一下元注解,然后对元注解中的@Retention做深入的讨论,在文章最后使用元注解写一个自定义注解来结尾. 一.结论: @Target:注解的作用目标 @Target(ElementTyp ...
- 使用spring aspect控制自定义注解
自定义注解:这里是一个处理异常的注解,当调用方法发生异常时,返回异常信息 /** * ErrorCode: * * @author yangzhenlong * @since 2016/7/21 */ ...
- spring AOP 和自定义注解进行身份验证
一个SSH的项目(springmvc+hibernate),需要提供接口给app使用.首先考虑的就是权限问题,app要遵循极简模式,部分内容无需验证,用过滤器不能解决某些无需验证的方法 所以最终选择用 ...
- Spring实现封装自定义注解@Trimmed清除字符串前后的空格
在Spring中实现字符串清除的方法有很多,原生方法String自带trim()方法,或者使用StringUtils提供的trim...方法. 通常可以将上面的方式封装成自定义注解的形式去实现来节省更 ...
- Spring Boot中自定义注解+AOP实现主备库切换
摘要: 本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的 ...
- Spring Boot实现自定义注解
在Spring Boot项目中可以使用AOP实现自定义注解,从而实现统一.侵入性小的自定义功能. 实现自定义注解的过程也比较简单,只需要3步,下面实现一个统一打印日志的自定义注解: 1. 引入AOP依 ...
- spring boot通过自定义注解和AOP拦截指定的请求
一 准备工作 1.1 添加依赖 通过spring boot创建好工程后,添加如下依赖,不然工程中无法使用切面的注解,就无法对制定的方法进行拦截 <dependency> <group ...
- spring + quartz 分布式自定义注解
相关技术 本文采用spring + quartz的方案.使用mysql作为任务的持久化,支持分布式. 自定义注解 1.启用定时任务 @Target(ElementType.TYPE) @Retenti ...
随机推荐
- C语言 链表操作
#include<stdio.h>#include<stdlib.h>struct node{ int data; struct node *next;};int ...
- Web前端入门第1问:英语是否很重要?有哪些前置条件?
HELLO,这里是大熊学习前端开发的入门笔记. 本系列笔记基于 windows 系统. 在入门之前,是否有这样的疑问: 程序员的英语是否很牛?毕竟程序员的代码像天书一样,比如这样: 答案是否定的. 英 ...
- 部署sing-box代理服务器绕过付费校园网上网
解决的问题 学校一般会有2个网络,一个是教学区的免费校园网,一个是寝室楼的付费校园网.如何不交钱也能在寝室楼上网是一个问题. 以及,如果校园网在12点之后断网,如果解决断网问题 sing-box Gi ...
- NSIS打包脚本模板
; Script generated by the HM NIS Edit Script Wizard. ; HM NIS Edit Wizard helper defines !define PRO ...
- 【SpringMVC】国际化&文件的上传&使用拦截器&异常处理
国际化 国际化概述 默认情况下,SpringMVC 根据 Accept-Language 参数判断客户端的本地化类型. 当接受到请求时,SpringMVC 会在上下文中查找一个本地化解析器(Local ...
- 关于TFDMemtable的使用场景【1】提供快速查询
建立内存表非常easy.看代码: begin createZipTable; FillZipCodeData; end: procdure CreateZipCodeTable; var Defs, ...
- datasnap的监督功能【2】-管理Session
1.服务端的Session是有TDSSession定义的.TDSSession提供了许多有用的方法和特性,再开发室取得服务or重要信息. 如Session状态.安排Session独享定时or自动执行工 ...
- 小了 60,500 倍,但更强;AI 的“深度诅咒”
作者:Ignacio de Gregorio 图片来自 Unsplash 的 Bahnijit Barman 几周前,我们看到 Anthropic 尝试训练 Claude 去通关宝可梦.模型是有点进展 ...
- Excel百万数据如何快速导入?
前言 今天要讨论一个让无数人抓狂的话题:如何高效导入百万级Excel数据. 去年有家公司找到我,他们的电商系统遇到一个致命问题:每天需要导入20万条商品数据,但一执行就卡死,最长耗时超过3小时. 更魔 ...
- 应急响应 - Linux基础篇
一.Linux应急响应流程 数据备份:所有涉及到分析以及证据的材料都需要提前进行备份,这样也方便之后还有分析人员或者防止数据被篡改或者覆盖. 备份用户信息文件 cat /etc/passwd > ...