标注注解作用的范围
类型 | 说明 |
---|---|
ElementType.TYPE | 类,接口(包括注解类型)或enum声明 |
ElementType.FIELD | 字段,枚举常量 |
ElementType.METHOD | 方法声明 |
ElementType.PARAMETER | 参数声明 |
ElementType.CONSTRUCTOR | 构造器声明 |
ElementType.LOCAL_VARIABLE | 局部变量声明 |
ElementType.PACKAGE | 包声明 |
ElementType.LOCAL_VARIABLE | 局部变量 |
ElementType.ANNOTATION_TYPE | 注解 |
表示在什么级别保存该注解信息
类型 | 说明 |
---|---|
RetentionPolicy.SOURCE | 注解仅存在于源码中,在class字节码文件中不包含 |
RetentionPolicy.CLASS | 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得 |
RetentionPolicy.RUNTIME | 注解会在class字节码文件中存在,在运行时可以通过反射获取到首 先要明确生命周期长度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。 |
将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。
Inherited 是继承的意思,但是他并不是说直接本身可以继承,而是说一个超类被@Inheritedh注解,
此处为何会讲解反射,因为注解和反射是密切相关的,没有反射,无法完成注解功能的解析。
class Method Field Constructor
java.lang.Class; 类 java.lang.reflect.Constructor; 构造器方法 java.lang.reflect.Field; 属性 java.lang.reflect.Method; 方法 java.lang.reflect.Modifier; 修饰符
1、源代码(source) 原代码不是指java文件,是class字节码文件 2、类加载(class) class字节码文件经类加载器classloader加载到虚拟机内存中,类加载器解析class文件生成Class类型的对象 3、运行时(runtime) newInstance()根据java类型生成对象
1、Class class=Class.forName("com.xx.xx.xx.Person"); 2、Class<Person> class=Person.class; 3、Person p=new Person(); Class class=p.getClass();
写一个注解,自定义返回自己的toString方法。返回自己想要的格式
完整代码可以去此项目下查看cloud-annotation
注解名称 | 功能 |
---|---|
@JsonFormat | 格式化功能 |
@JsonIgnore | 忽略功能 |
@JsonProperty | 属性名 |
/** * 作用于属性上,用户按要求格式化日期 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface JsonFormat { String pattern() default "yyyy-MM-dd HH:mm:ss"; }
/** * 作用在属性上,用于忽略一些属性 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface JsonIgnore { }
/** * 属性别名 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface JsonProperty { String value(); //使用的时候必须给值
package com.xwb.springcloud.annotation.json; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.Date; @SuppressWarnings("all") public class JSON { public static String toJSONString(Object object) { StringBuffer json = new StringBuffer(); try { //1、得到object的Class对象 Class<?> clazz = object.getClass(); //2、得到class里面的所有属性 Field[] fields = clazz.getDeclaredFields(); //3、循环遍历所有属性病打破属性的访问权限 int index = 0; //得到属性长度 int length = fields.length; json.append("{"); for (Field field : fields) { index++; //判断属性上是否有忽略的注解 if (field.isAnnotationPresent(JsonIgnore.class)) { continue; } //私有变量可读 field.setAccessible(true); //4得到属性名作为json的key String name = field.getName(); //5、得到属性值作为json的value Object value = field.get(object); //判断属性上是否有更改名字的注解 if (field.isAnnotationPresent(JsonProperty.class)) { //有的话取出注解上的名字 JsonProperty annotation = field.getAnnotation(JsonProperty.class); name = annotation.value(); } json.append("\"" + name + "\""); if (value instanceof String) { json.append(":\"" + value.toString() + "\""); } else if (value instanceof Date) { //此处如果是日期的话,则判断是否有日起格式化的注解 Date date = (Date) value; if (field.isAnnotationPresent(JsonFormat.class)) { JsonFormat format = field.getAnnotation(JsonFormat.class); json.append(":\"" + parseDateToStr(date, format.pattern()) + "\""); } else { json.append(":\"" + date.getTime() + "\""); } } else { json.append(":" + value.toString()); } if (index != length) { json.append(","); } } json.append("}"); return json.toString(); } catch (Exception e) { System.out.println(e.getCause()); } return null; } public static String parseDateToStr(Date date, String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); return sdf.format(date); } }
说明:
定义的注解,没有任何作用,但是想让注解发挥它的作用,就要定义相应的方法去解析他,然后让他发挥作用。
谁定义的注解谁去解析。而不是说自己定义的注解让java去解析,他是不识别的。
public class TestJSON { public static void main(String[] args) { User user = new User(1, "张三", "宁夏银川", new Date()); String s = JSON.toJSONString(user); System.out.println(s); } }
{“user_name”:“张三”,“user_address”:“宁夏银川”,“birth”:“2021-11-12”}
总结:注解本身没有任何作用,只是申明的而已,具体起作用是定义该注解的开发者想让其起到什么功能,然后再对应解析的方法中运用反射获取类、属性、方法、参数…上是否有该注解,有的话(xxx instanceof xxx)根据开发者自己的想法去实现该功能方法。
查找源码中的类或者方法使用的快捷键是【ctrl+n】
spring-webmvc-5.2.2.RELEASE.jar包下的RequestResponseBodyMethodProcessor类进行解析
关于该注解的详细说明请观看此博客@RequestBody
mybatis-3.4.4.jar包下的MapperAnnotationBuilder类parse方法RequestResponseBodyMethodProcessor
关于@Mapper请看此博客@Mapper
spring-context-5.2.2.RELEASE.jar包下的ConfigurationClassPostProcessor类
源码具体详解可以查看此博主博客@Configuration
spring-cloud-openfeign-core-2.2.1.RELEASE.jar包的FeignClientsRegistrar类
关于@FeignClient的源码解析请看此博客@FeignClient