java annotation 作用_Java关于Annotation详解

Annotation的架构图:

2af268c710af49fda9c1916a16b1dddb.png

可以看出:

(01) 1个Annotation 和 1个RetentionPolicy关联。

可以理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性。

(02) 1个Annotation 和 1~n个ElementType关联。

可以理解为:对于每1个Annotation对象,可以有若干个ElementType属性。

(03) Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override等等。

Annotation 的每一个实现类,都“和1个RetentionPolicy关联”并且“和1~n个ElementType关联”。

Annotation组成成分

Annotation.java

package java.lang.annotation;public interfaceAnnotation {

boolean equals(Object obj);inthashCode();

String toString();

Class extends Annotation>annotationType();

}

ElementType.java

package java.lang.annotation;public enumElementType {

TYPE,/*类、接口(包括注释类型)或枚举声明*/FIELD,/*字段声明(包括枚举常量)*/METHOD,/*方法声明*/PARAMETER,/*参数声明*/CONSTRUCTOR,/*构造方法声明*/LOCAL_VARIABLE,/*局部变量声明*/ANNOTATION_TYPE,/*注释类型声明*/PACKAGE/*包声明*/}

RetentionPolicy.java

package java.lang.annotation;public enumRetentionPolicy {

SOURCE,/*Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了*/CLASS,/*编译器将Annotation存储于类对应的.class文件中。默认行为*/RUNTIME/*编译器将Annotation存储于class文件中,并且可由JVM读入*/}

说明:

(01) Annotation 是个接口。

“每1个Annotation” 都与 “1个RetentionPolicy”关联,并且与 “1~n个ElementType”关联。可以通俗的理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性;至于ElementType属性,则有1~n个。

(02) ElementType 是Enum枚举类型,用来指定Annotation的类型。

“每1个Annotation” 都与 “1~n个ElementType”关联。当Annotation与某个ElementType关联时,就意味着:Annotation有了某种用途。

例如,若一个Annotation对象是METHOD类型,则该Annotation只能用来修饰方法。

(03) RetentionPolicy 是Enum枚举类型,用来指定Annotation的策略。通俗点说,就是不同RetentionPolicy类型的Annotation的作用域不同。

“每1个Annotation” 都与 “1个RetentionPolicy”关联。

a) 若Annotation的类型为 SOURCE,则意味着:Annotation仅存在于编译器处理期间,编译器处理完之后,该Annotation就没用了。

例如,“ @Override ”标志就是一个Annotation。当它修饰一个方法的时候,就意味着该方法覆盖父类的方法;并且在编译期间会进行语法检查!编译器处理完                          后,“@Override”就没有任何作用了。

b) 若Annotation的类型为 CLASS,则意味着:编译器将Annotation存储于类对应的.class文件中,是Annotation的默认行为。

c) 若Annotation的类型为 RUNTIME,则意味着:编译器将Annotation存储于class文件中,并且可由JVM读入。

这时,只需要记住“每1个Annotation” 都与 “1个RetentionPolicy”关联,并且与 “1~n个ElementType”关联。

示例

@Documented

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)public@interface MyAnnotation1 {

}

说明:

定义一个Annotation,名字是MyAnnotation1。定义了MyAnnotation1之后,可以在代码中通过“@MyAnnotation1”来使用它。

其它的,@Documented, @Target, @Retention, @interface都是来修饰MyAnnotation1的。下面分别说说它们的含义:

(01) @interface

使用@interface定义注解时,意味着它实现java.lang.annotation.Annotation接口,即该注解就是一个Annotation。

定义Annotation时,@interface是必须的

注意:和我们通常的implemented实现接口的方法不同。Annotation接口的实现细节都由编译器完成。通过@interface定义注解后,该注解不能继承其他的注解或接口。

(02) @Documented

类和方法的Annotation在缺省情况下是不出现在javadoc中的。如果使用@Documented修饰该Annotation,则表示它可以出现在javadoc中。

定义Annotation时,@Documented可有可无;若没有定义,则Annotation不会出现在javadoc中。

(03) @Target(ElementType.TYPE)

ElementType 是Annotation的类型属性。而@Target的作用,就是来指定Annotation的类型属性。

@Target(ElementType.TYPE) 的意思就是指定该Annotation的类型是ElementType.TYPE。这就意味着,MyAnnotation1是来修饰“类、接口(包括注释类型)或枚举声明”的注解。

定义Annotation时,@Target可有可无。若有@Target,则该Annotation只能用于它所指定的地方;若没有@Target,则该Annotation可以用于任何地方。

(04) @Retention(RetentionPolicy.RUNTIME)

RetentionPolicy 是Annotation的策略属性,而@Retention的作用,就是指定Annotation的策略属性。

@Retention(RetentionPolicy.RUNTIME) 的意思就是指定该Annotation的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将该Annotation信息保留在.class文件中,并且能被虚拟机读取。

定义Annotation时,@Retention可有可无。若没有@Retention,则默认是RetentionPolicy.CLASS。

Annotation

@interface用来声明Annotation,@Documented用来表示该Annotation是否会出现在javadoc中, @Target用来指定Annotation的类型,@Retention用来指定Annotation的策略。

5d67504540412341db7f229b147fe110.png

java 常用的Annotation:

@Deprecated -- @Deprecated 所标注内容,不再被建议使用。

@Override-- @Override 只能标注方法,表示该方法覆盖父类中的方法。

@Documented-- @Documented 所标注内容,可以出现在javadoc中。

@Inherited-- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。

@Retention-- @Retention只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性。

@Target-- @Target只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性。

@SuppressWarnings-- @SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默。

@Deprecated 的定义如下:

@Documented

@Retention(RetentionPolicy.RUNTIME)public@interface Deprecated {

}

说明:

(01) @interface -- 它的用来修饰Deprecated,意味着Deprecated实现了java.lang.annotation.Annotation接口;即Deprecated就是一个注解。

(02) @Documented -- 作用是说明该注解能出现在javadoc中。

(03) @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定Deprecated的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将Deprecated的信息保留在.class文件中,并且能被虚拟机读取。

(04) @Deprecated 所标注内容,不再被建议使用。

@Inherited 的定义如下

@Documented

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.ANNOTATION_TYPE)public@interface Inherited {

}

说明:

(01) @interface            -- 用来修饰Inherited,意味着Inherited实现了java.lang.annotation.Annotation接口;即Inherited就是一个注解。

(02) @Documented      -- 作用是说明该注解能出现在javadoc中。

(03) @Retention(RetentionPolicy.RUNTIME)    -- 作用是指定Inherited的策略是RetentionPolicy.RUNTIME。这就意味着,编译器会将Inherited的信息保留在.class文件中,并且能被虚拟机读取。

(04) @Target(ElementType.ANNOTATION_TYPE) -- 作用是指定Inherited的类型是ANNOTATION_TYPE。这就意味着,@Inherited只能被用来标注“Annotation类型”。

(05) @Inherited 的含义是,它所标注的Annotation将具有继承性。

定义了某个Annotaion,名称是MyAnnotation,并且MyAnnotation被标注为@Inherited。某个类Base使用了MyAnnotation,则Base具有了“具有了注解MyAnnotation”;Sub继承了Base,由于MyAnnotation是@Inherited的(具有继承性),所以,Sub也“具有了注解MyAnnotation”。

/**

* @Inherited 演示示例

**/package com.skywang.annotation;

import java.lang.annotation.Target;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Inherited;/**

* 自定义的Annotation。*/@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@interface Inheritable

{

}

@InheritableclassInheritableFather

{publicInheritableFather() {//InheritableBase是否具有 Inheritable Annotation

System.out.println("InheritableFather:"+InheritableFather.class.isAnnotationPresent(Inheritable.class));

}

}/**

* InheritableSon 类只是继承于 InheritableFather,*/

public classInheritableSon extends InheritableFather

{publicInheritableSon() {

super();//调用父类的构造函数//InheritableSon类是否具有 Inheritable Annotation

System.out.println("InheritableSon:"+InheritableSon.class.isAnnotationPresent(Inheritable.class));

}public static voidmain(String[] args)

{

InheritableSonis = newInheritableSon();

}

}

结果:true true

对InheritableSon.java进行修改:注释掉“Inheritable的@Inherited注解”:返回 true false

@SuppressWarnings 的定义如下:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})

@Retention(RetentionPolicy.SOURCE)public@interface SuppressWarnings {

String[] value();

}

说明:

(01) @interface -- 它的用来修饰SuppressWarnings,意味着SuppressWarnings实现java.lang.annotation.Annotation接口;即SuppressWarnings就是一个注解。

(02) @Retention(RetentionPolicy.SOURCE) -- 作用是指定SuppressWarnings的策略是RetentionPolicy.SOURCE。意味着,SuppressWarnings信息仅存在于编译器处理期间,编译器处理完之后SuppressWarnings就没有作用了。

(03) @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) -- 它的作用是指定SuppressWarnings的类型同时包括TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE。

TYPE意味着,它能标注“类、接口(包括注释类型)或枚举声明”。

FIELD意味着,它能标注“字段声明”。

METHOD意味着,它能标注“方法”。

PARAMETER意味着,它能标注“参数”。

CONSTRUCTOR意味着,它能标注“构造方法”。

LOCAL_VARIABLE意味着,它能标注“局部变量”。

(04) String[] value(); 意味着,SuppressWarnings能指定参数

(05) SuppressWarnings 的作用是,让编译器对“它所标注的内容”的某些警告保持静默。例如,"@SuppressWarnings(value={"deprecation", "unchecked"})" 表示对“它所标注的内容”中的 “SuppressWarnings不再建议使用警告”和“未检查的转换时的警告”保持沉默。

作用:

让编译器进行编译检查的作用

b14325e360aec59842145bb37f8af566.png

若某个方法被 @Override的 标注,则意味着该方法会覆盖父类中的同名方法。如果有方法被@Override标示,但父类中却没有“被@Override标注”的同名方法,则编译器会报错

反射中使用Annotation

import java.lang.annotation.Annotation;

import java.lang.annotation.Target;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Inherited;

import java.lang.reflect.Method;/**

* Annotation在反射函数中的使用示例*/@Retention(RetentionPolicy.RUNTIME)

@interface MyAnnotation {

String[] value()default "unknown";

}/**

* Person类。它会使用MyAnnotation注解。*/

classPerson {/**

* empty()方法同时被 "@Deprecated" 和 “@MyAnnotation(value={"a","b"})”所标注

* (01) @Deprecated, 意味着empty()方法,不再被建议使用

* (02) @MyAnnotation, 意味着empty() 方法对应的MyAnnotation的value值是默认值"unknown"*/@MyAnnotation

@Deprecatedpublic voidempty(){

System.out.println("\nempty");

}/**

* sombody() 被 @MyAnnotation(value={"girl","boy"}) 所标注,

* @MyAnnotation(value={"girl","boy"}), 意味着MyAnnotation的value值是{"girl","boy"}*/@MyAnnotation(value={"girl","boy"})public void somebody(String name, intage){

System.out.println("\nsomebody:"+name+","+age);

}

}public classAnnotationTest {public static voidmain(String[] args) throws Exception {//新建Person

Person person = newPerson();//获取Person的Class实例

Class c = Person.class;//获取 somebody() 方法的Method实例

Method mSomebody = c.getMethod("somebody", new Class[]{String.class, int.class});//执行该方法

mSomebody.invoke(person, new Object[]{"lily", 18});

iteratorAnnotations(mSomebody);//获取 somebody() 方法的Method实例

Method mEmpty = c.getMethod("empty", newClass[]{});//执行该方法

mEmpty.invoke(person, newObject[]{});

iteratorAnnotations(mEmpty);

}public static voiditeratorAnnotations(Method method) {//判断 somebody() 方法是否包含MyAnnotation注解

if(method.isAnnotationPresent(MyAnnotation.class)){//获取该方法的MyAnnotation注解实例

MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);//获取 myAnnotation的值,并打印出来

String[] values =myAnnotation.value();for(String str:values)

System.out.printf(str+",");

System.out.println();

}//获取方法上的所有注解,并打印出来

Annotation[] annotations =method.getAnnotations();for(Annotation annotation : annotations){

System.out.println(annotation);

}

}

}

运行结果:

somebody: lily, 18

girl, boy,

@com.skywang.annotation.MyAnnotation(value=[girl, boy])

empty

unknown,

@com.skywang.annotation.MyAnnotation(value=[unknown])

@java.lang.Deprecated()

快捷方式就是注解中定义了名为value的元素,并且在使用该注解时,如果该元素是唯一需要赋值的一个元素,那么此时无需使用key=value的语法,而只需在括号内给出value元素所需的值即可。这可以应用于任何合法类型的元素,记住,这限制了元素名必须为value,简单案例如下

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;//定义注解

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

@interface IntegerVaule{int value() default 0;

String name()default "";

}//使用注解

public classQuicklyWay {//当只想给value赋值时,可以使用以下快捷方式

@IntegerVaule(20)public intage;//当name也需要赋值时必须采用key=value的方式赋值

@IntegerVaule(value = 10000,name = "MONEY")public intmoney;

}

运行时注解处理器

利用运行时注解来组装数据库SQL的构建语句的过程

/**

* 表注解*/@Target(ElementType.TYPE)//只能应用于类上

@Retention(RetentionPolicy.RUNTIME)//保存到运行时

public@interface DBTable {

String name()default "";

}/**

* 注解Integer类型的字段*/@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)public@interface SQLInteger {//该字段对应数据库表列名

String name() default "";//嵌套注解

Constraints constraint() default@Constraints;

}/**

* 注解String类型的字段*/@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)public@interface SQLString {//对应数据库表的列名

String name() default "";//列类型分配的长度,如varchar(30)的30

int value() default 0;

Constraints constraint()default@Constraints;

}/**

* 约束注解*/@Target(ElementType.FIELD)//只能应用在字段上

@Retention(RetentionPolicy.RUNTIME)public@interface Constraints {//判断是否作为主键约束

boolean primaryKey() default false;//判断是否允许为null

boolean allowNull() default false;//判断是否唯一

boolean unique() default false;

}/**

* 数据库表Member对应实例类bean*/@DBTable(name= "MEMBER")public classMember {//主键ID

@SQLString(name = "ID",value = 50, constraint =@Constraints(primaryKey= true))privateString id;

@SQLString(name= "NAME" , value = 30)privateString name;

@SQLInteger(name= "AGE")private intage;

@SQLString(name= "DESCRIPTION" ,value = 150,

constraint= @Constraints(allowNull = true))private String description;//个人描述//省略set get.....

}

import java.lang.annotation.Annotation;

import java.lang.reflect.Field;

import java.util.ArrayList;

import java.util.List;/**

* 运行时注解处理器,构造表创建语句*/

public classTableCreator {public staticString createTableSql(String className) throws ClassNotFoundException {

Class> cl =Class.forName(className);

DBTable dbTable= cl.getAnnotation(DBTable.class);//如果没有表注解,直接返回

if(dbTable == null) {

System.out.println("No DBTable annotations in class"+className);return null;

}

String tableName=dbTable.name();//If the name is empty, use the Class name:

if(tableName.length() < 1)

tableName=cl.getName().toUpperCase();

List columnDefs = new ArrayList();//通过Class类API获取到所有成员字段

for(Field field : cl.getDeclaredFields()) {

String columnName= null;//获取字段上的注解

Annotation[] anns =field.getDeclaredAnnotations();if(anns.length < 1)continue; //Not a db table column//判断注解类型

if(anns[0] instanceof SQLInteger) {

SQLInteger sInt= (SQLInteger) anns[0];//获取字段对应列名称,如果没有就是使用字段名称替代

if(sInt.name().length() < 1)

columnName=field.getName().toUpperCase();elsecolumnName=sInt.name();//构建语句

columnDefs.add(columnName + "INT" +getConstraints(sInt.constraint()));

}//判断String类型

if(anns[0] instanceof SQLString) {

SQLString sString= (SQLString) anns[0];//Use field name if name not specified.

if(sString.name().length() < 1)

columnName=field.getName().toUpperCase();elsecolumnName=sString.name();

columnDefs.add(columnName+ "VARCHAR(" +sString.value()+ ")" +getConstraints(sString.constraint()));

}

}//数据库表构建语句

StringBuilder createCommand = newStringBuilder("CREATE TABLE" + tableName + "(");for(String columnDef : columnDefs)

createCommand.append("\n" + columnDef + ",");//Remove trailing comma

String tableCreate =createCommand.substring(0, createCommand.length() - 1) + ");";returntableCreate;

}/**

* 判断该字段是否有其他约束

* @param con

* @return*/

private staticString getConstraints(Constraints con) {

String constraints= "";if(!con.allowNull())

constraints+= "NOT NULL";if(con.primaryKey())

constraints+= "PRIMARY KEY";if(con.unique())

constraints+= "UNIQUE";returnconstraints;

}public static voidmain(String[] args) throws Exception {

String[] arg={"com.zejian.annotationdemo.Member"};for(String className : arg) {

System.out.println("Table Creation SQL for" +className+ "is :\n" +createTableSql(className));

}/**

* 输出结果:

Table Creation SQL for com.zejian.annotationdemo.Member is :

CREATE TABLE MEMBER(

ID VARCHAR(50) NOT NULL PRIMARY KEY,

NAME VARCHAR(30) NOT NULL,

AGE INT NOT NULL,

DESCRIPTION VARCHAR(150)

);*/}

}

元注解@Repeatable

元注解@Repeatable是JDK1.8新加入的,它表示在同一个位置重复相同的注解。在没有该注解前,一般是无法在同一个类型上使用相同的注解的

//Java8前无法这样使用

@FilterPath("/web/update")

@FilterPath("/web/add")public class A {}

Java8前如果是想实现类似的功能,我们需要在定义@FilterPath注解时定义一个数组元素接收多个值如下

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)public@interface FilterPath {

String [] value();

}//使用

@FilterPath({"/update","/add"})public class A { }

Java8新增了@Repeatable注解后就可以采用如下的方式定义并使用

//使用Java8新增@Repeatable原注解

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Repeatable(FilterPaths.class)//参数指明接收的注解class

public@interface FilterPath {

String value();

}

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@interface FilterPaths {

FilterPath[] value();

}//使用案例

@FilterPath("/web/update")

@FilterPath("/web/add")

@FilterPath("/web/delete")class AA{ }

通过使用@Repeatable后,将使用@FilterPaths注解作为接收同一个类型上重复注解的容器,而每个@FilterPath则负责保存指定的路径串。为了处理上述的新增注解,Java8还在AnnotatedElement接口新增了getDeclaredAnnotationsByType() 和 getAnnotationsByType()两个方法并在接口给出了默认实现,在指定@Repeatable的注解时,可以通过这两个方法获取到注解相关信息。但请注意,旧版API中的getDeclaredAnnotation()和 getAnnotation()是不对@Repeatable注解的处理的(除非该注解没有在同一个声明上重复出现)。注意getDeclaredAnnotationsByType方法获取到的注解不包括父类,其实当 getAnnotationsByType()方法调用时,其内部先执行了getDeclaredAnnotationsByType方法,只有当前类不存在指定注解时,getAnnotationsByType()才会继续从其父类寻找,但请注意如果@FilterPath和@FilterPaths没有使用了@Inherited的话,仍然无法获取。下面通过代码来演示:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

//使用Java8新增@Repeatable原注解

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Repeatable(FilterPaths.class)public@interface FilterPath {

String value();

}

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@interface FilterPaths {

FilterPath[] value();

}

@FilterPath("/web/list")classCC { }//使用案例

@FilterPath("/web/update")

@FilterPath("/web/add")

@FilterPath("/web/delete")classAA extends CC{public static voidmain(String[] args) {

Class> clazz = AA.class;//通过getAnnotationsByType方法获取所有重复注解

FilterPath[] annotationsByType = clazz.getAnnotationsByType(FilterPath.class);

FilterPath[] annotationsByType2= clazz.getDeclaredAnnotationsByType(FilterPath.class);if (annotationsByType != null) {for(FilterPath filter : annotationsByType) {

System.out.println("1:"+filter.value());

}

}

System.out.println("-----------------");if (annotationsByType2 != null) {for(FilterPath filter : annotationsByType2) {

System.out.println("2:"+filter.value());

}

}

System.out.println("使用getAnnotation的结果:"+clazz.getAnnotation(FilterPath.class));/**

* 执行结果(当前类拥有该注解FilterPath,则不会从CC父类寻找)

1:/web/update

1:/web/add

1:/web/delete

-----------------

2:/web/update

2:/web/add

2:/web/delete

使用getAnnotation的结果:null*/}

}

View Code

执行结果来看如果当前类拥有该注解@FilterPath,则getAnnotationsByType方法不会从CC父类寻找,下面看看另外一种情况,即AA类上没有@FilterPath注解

//使用Java8新增@Repeatable原注解

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Inherited//添加可继承元注解

@Repeatable(FilterPaths.class)public@interface FilterPath {

String value();

}

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Inherited//添加可继承元注解

@interface FilterPaths {

FilterPath[] value();

}

@FilterPath("/web/list")

@FilterPath("/web/getList")classCC { }//AA上不使用@FilterPath注解,getAnnotationsByType将会从父类查询

classAA extends CC{public static voidmain(String[] args) {

Class> clazz = AA.class;//通过getAnnotationsByType方法获取所有重复注解

FilterPath[] annotationsByType = clazz.getAnnotationsByType(FilterPath.class);

FilterPath[] annotationsByType2= clazz.getDeclaredAnnotationsByType(FilterPath.class);if (annotationsByType != null) {for(FilterPath filter : annotationsByType) {

System.out.println("1:"+filter.value());

}

}

System.out.println("-----------------");if (annotationsByType2 != null) {for(FilterPath filter : annotationsByType2) {

System.out.println("2:"+filter.value());

}

}

System.out.println("使用getAnnotation的结果:"+clazz.getAnnotation(FilterPath.class));/**

* 执行结果(当前类没有@FilterPath,getAnnotationsByType方法从CC父类寻找)

1:/web/list

1:/web/getList

-----------------

使用getAnnotation的结果:null*/}

}

注意定义@FilterPath和@FilterPath时必须指明@Inherited,getAnnotationsByType方法否则依旧无法从父类获取@FilterPath注解,这是为什么呢,不妨看看getAnnotationsByType方法的实现源码:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

//接口默认实现方法

default T[] getAnnotationsByType(ClassannotationClass) {//先调用getDeclaredAnnotationsByType方法

T[] result =getDeclaredAnnotationsByType(annotationClass);//判断当前类获取到的注解数组是否为0

if (result.length == 0 && this instanceof Class &&

//判断定义注解上是否使用了@Inherited元注解

AnnotationType.getInstance(annotationClass).isInherited()) { //Inheritable//从父类获取

Class> superClass = ((Class>) this).getSuperclass();if (superClass != null) {

result=superClass.getAnnotationsByType(annotationClass);

}

}returnresult;

}

View Code

参考:

http://www.cnblogs.com/skywang12345/p/3344137.html#top

https://blog.csdn.net/javazejian/article/details/71860633(推荐)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值