JDK1.8的新特性——注解Annotation更多场景的使用

来源:互联网 发布:php bin2hex写入文件 编辑:程序博客网 时间:2024/06/05 13:55

最近工作不是很忙,领导发了一遍文章,说某某公司人员出了公司都没有猎头要了,细思极恐。想想怎么办呢,项目的框架非常复杂,到处都是注解,已经到了无法看懂的地步了。像spring-boot这样的大面积注解使用,我已经开始怀疑是否必要。项目启动速度如此之慢,也是超出了我的预期,可是苦于无法改善。因为以前有通过debug的方式看懂过框架,所以一开始就想着干脆花点时间把spring看懂吧。但是事实确实非常恐怖的,因为发现看着看着很多代码时jdk的还要看半天,导致效率极低。又准备找一本教材看看,不巧的是教材的序里面就说过了作者看了半年时间。两方一权衡,想想这不是办法,遂决定先把JDK给看仔细了。我画了一个思维导图,首先从java.lang包看起,第一个类就是Class类。其中花的我时间最长的方法,却是几个现在分词和过去分词的问题,如Declared和Declaring,当然还有本文要说明的重点Annotated。

· 1.JDK1.8中 对Annotation的target(ElementType)增加了两个枚举值

 

public enum ElementType {    /** Class, interface (including annotation type), or enum declaration */    TYPE,    /** Field declaration (includes enum constants) */    FIELD,    /** Method declaration */    METHOD,    /** Formal parameter declaration */    PARAMETER,    /** Constructor declaration */    CONSTRUCTOR,    /** Local variable declaration */    LOCAL_VARIABLE,    /** Annotation type declaration */    ANNOTATION_TYPE,    /** Package declaration */    PACKAGE,    /**     * Type parameter declaration     *     * @since 1.8     */    TYPE_PARAMETER,    /**     * Use of a type     *     * @since 1.8     */    TYPE_USE}

TYPE_PARAMETER 和 TYPE_USE

2.增加了一个元注解 @Repeatable

如下:

这是定义可重复的地方,经过试验,TYPE_PARAMETER 和 TYPE_USE 不能再target上面使用

@Target(value = { ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE })@Retention(RetentionPolicy.RUNTIME)@Documentedpublic  @interface Roles {Role[] value();}



@Target(value = { ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE, TYPE_USE })@Repeatable(value = Roles.class)@Retention(RetentionPolicy.RUNTIME)public @interface Role {String name();}

使用注解的地方:

@Role(name = "1")@Role(name = "2")@Role(name = "3")@Role(name = "4")@Role(name = "5")@Role(name = "6")public interface Bar {}


3.增加了AnnotatedType 接口

该接口的实现类有多种,基本上都是关于某种类型的封装,如一般的Class的封装sun.reflect.annotation.AnnotatedTypeFactory.AnnotatedTypeBaseImpl


其中

type代表了 “被注解“”的类型

decl(declared)代表注解声明的地方

annotations 代表该注解

因为是新语法,理解起来比较绕口,下面说明下哪些地方会返回AnnotatedType 接口

(返回值的注解和返回类型一起封装,注解本身必须满足TYPE_PARAMETER 或者 TYPE_USE)


java.lang.Class.getAnnotatedInterfaces() 获取父类(在继承时候添加了注解)


java.lang.Class.getAnnotatedSuperclass() 获取接口(在继承时候添加了注解)


java.lang.reflect.Method.getAnnotatedReturnType()  为了获取返回值上面的注解,将返回值和注解一起包装起来

java.lang.reflect.Method.getAnnotatedReceiverType() jdk8的新语法,传入参数第一个参数可以用当前类 名字为this来代替

java.lang.reflect.Method.getAnnotatedParameterTypes()  为了获取参数上面的注解,将参数和注解一起包装起来

java.lang.reflect.Method.getAnnotatedExceptionTypes() 为了获取异常上面的注解,将异常和注解一起包装起来


java.lang.reflect.Constructor.getAnnotatedReturnType() 同method

java.lang.reflect.Constructor.getAnnotatedReceiverType() 暂时不知道怎么使用

java.lang.reflect.Constructor.getAnnotatedParameterTypes() 同method

java.lang.reflect.Constructor.getAnnotatedExceptionTypes() 同method


java.lang.reflect.Field.getAnnotatedType()


java.lang.reflect.Parameter.getAnnotatedType()


package reflect;import static java.lang.annotation.ElementType.*;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import java.lang.reflect.AnnotatedType;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Parameter;import java.util.Arrays;public class Foo {public static void main(String[] args) throws NoSuchMethodException, SecurityException, Exception {Class<Foo1> clz = Foo1.class;System.out.println("clz.getAnnotatedInterfaces()");printAnnotatedType(clz.getAnnotatedInterfaces());System.out.println("clz.getAnnotatedSuperclass()");printAnnotatedType(clz.getAnnotatedSuperclass());Method method = clz.getMethod("getFoo2", String.class);System.out.println("method.getAnnotatedReturnType()");printAnnotatedType(method.getAnnotatedReturnType());System.out.println("method.getAnnotatedReceiverType()");printAnnotatedType(method.getAnnotatedReceiverType());System.out.println("method.getAnnotatedParameterTypes()");printAnnotatedType(method.getAnnotatedParameterTypes());System.out.println("method.getAnnotatedExceptionTypes()");printAnnotatedType(method.getAnnotatedExceptionTypes());Constructor<Foo1> constructor = clz.getConstructor(String.class);System.out.println("constructor.getAnnotatedReturnType()");printAnnotatedType(constructor.getAnnotatedReturnType());System.out.println("constructor.getAnnotatedReceiverType()");printAnnotatedType(constructor.getAnnotatedReceiverType());System.out.println("constructor.getAnnotatedParameterTypes()");printAnnotatedType(constructor.getAnnotatedParameterTypes());System.out.println("constructor.getAnnotatedExceptionTypes()");printAnnotatedType(constructor.getAnnotatedExceptionTypes());Field field = clz.getField("foo2");System.out.println("field.getAnnotatedType()");printAnnotatedType(field.getAnnotatedType());Parameter[] parameter = method.getParameters();System.out.println("parameter[0].getAnnotatedType()");printAnnotatedType(parameter[0].getAnnotatedType());}private static void printAnnotatedType(AnnotatedType[] annotatedTypes) {for (AnnotatedType annotatedType : annotatedTypes) {System.out.println(Arrays.toString(annotatedType.getAnnotations()));System.out.println(annotatedType.getType());}}private static void printAnnotatedType(AnnotatedType annotatedType) {System.out.println(Arrays.toString(annotatedType.getAnnotations()));System.out.println(annotatedType.getType());}}@Customclass Foo1 extends @Custom Employee implements @Custom Bar {public @Custom String foo2;public @Custom Foo1(@Custom String foo2) throws @Custom Exception {this.foo2 = foo2;}public @Custom String getFoo2(@Custom Foo1 this,@Custom String foo3) throws @Custom Exception {return   foo3;}}// So that annotation metadata is available at run time@Retention(RetentionPolicy.RUNTIME)// TYPE_USE being the important one@Target(value = { ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE, TYPE_PARAMETER,TYPE_USE })@interface Custom {}


输出结果

clz.getAnnotatedInterfaces()[@reflect.Custom()]interface reflect.Barclz.getAnnotatedSuperclass()[@reflect.Custom()]class reflect.Employeemethod.getAnnotatedReturnType()[@reflect.Custom()]class java.lang.Stringmethod.getAnnotatedReceiverType()[@reflect.Custom()]class reflect.Foo1method.getAnnotatedParameterTypes()[@reflect.Custom()]class java.lang.Stringmethod.getAnnotatedExceptionTypes()[@reflect.Custom()]class java.lang.Exceptionconstructor.getAnnotatedReturnType()[@reflect.Custom()]class reflect.Foo1constructor.getAnnotatedReceiverType()[]class reflect.Foo1constructor.getAnnotatedParameterTypes()[@reflect.Custom()]class java.lang.Stringconstructor.getAnnotatedExceptionTypes()[@reflect.Custom()]class java.lang.Exceptionfield.getAnnotatedType()[@reflect.Custom()]class java.lang.Stringparameter[0].getAnnotatedType()[@reflect.Custom()]class java.lang.String