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

最近工作不是很忙,领导发了一遍文章,说某某公司人员出了公司都没有猎头要了,细思极恐。想想怎么办呢,项目的框架非常复杂,到处都是注解,已经到了无法看懂的地步了。像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)
@Documented
public  @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());
	}
}

@Custom
class 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.Bar
clz.getAnnotatedSuperclass()
[@reflect.Custom()]
class reflect.Employee
method.getAnnotatedReturnType()
[@reflect.Custom()]
class java.lang.String
method.getAnnotatedReceiverType()
[@reflect.Custom()]
class reflect.Foo1
method.getAnnotatedParameterTypes()
[@reflect.Custom()]
class java.lang.String
method.getAnnotatedExceptionTypes()
[@reflect.Custom()]
class java.lang.Exception
constructor.getAnnotatedReturnType()
[@reflect.Custom()]
class reflect.Foo1
constructor.getAnnotatedReceiverType()
[]
class reflect.Foo1
constructor.getAnnotatedParameterTypes()
[@reflect.Custom()]
class java.lang.String
constructor.getAnnotatedExceptionTypes()
[@reflect.Custom()]
class java.lang.Exception
field.getAnnotatedType()
[@reflect.Custom()]
class java.lang.String
parameter[0].getAnnotatedType()
[@reflect.Custom()]
class java.lang.String


猜你喜欢

转载自blog.csdn.net/u014112608/article/details/73526554