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