1. Repeatable注解的定義
java8以后支持在同一個地方(某個方法或者某個類等)加上相同的注解,前提是要使用@Repeatable
注解,但是在用之前必須知道如何定義一個自定義注解:
自定義注解示例:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Repeatable(ActionUnlockChecks.class)
public @interface ActionUnlockCheck {
int actionType();
}
@Retention
@Retention
注解有一個屬性value
蹦哼,是RetentionPolicy
枚舉類型Rentention
搭配RententionPolicy
使用。RetentionPolicy
有3個值:CLASS
RUNTIME
SOURCE
按生命周期來劃分可分為3類:
RetentionPolicy.SOURCE
:注解只保留在源文件,當Java文件編譯成class文件的時候沦零,注解被遺棄;
RetentionPolicy.CLASS
:注解被保留到class文件货岭,但jvm加載class文件時候被遺棄路操,這是默認的生命周期疾渴;
RetentionPolicy.RUNTIME
:注解不僅被保存到class文件中,jvm加載class文件之后屯仗,仍然存在搞坝;
一般要用反射獲得注解就要使用RUNTIME
@Target
注解的作用域,屬性value
是數(shù)組魁袜,可以如示例所示填多個作用域桩撮,常用的有:TYPE
,METHOD
,PARAMETER
,CONSTRUCTOR
等@Repeatable
屬性value
的類型是Class類型,這里創(chuàng)建了一個另一個自定義注解峰弹,后面稱之為父注解店量,之前的稱之為子注解,示例代碼如下:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface ActionUnlockChecks {
ActionUnlockCheck[] value();
}
父注解必須有以下特征:
1:作用域必須大于等于子注解
2:父注解的周期要比子注解的周期要小或相同(注意:SOURCE(源碼) < CLASS (字節(jié)碼) < RUNTIME(運行))
3:父注解的value的類型是子注解類型的數(shù)組
2. Repeatable注解與反射
java反射是可以得到作用域RUNTIME
的注解的鞠呈,通過比如java.lang.Class#getAnnotation
方法:
ActionUnlockCheck annotation = joinPoint.getTarget().getClass().getAnnotation(ActionUnlockCheck.class);
但是這就有疑問了:既然注解是可重復的融师,那這個方法的返回值應該是數(shù)組而不是單個?
于是略加研究后發(fā)現(xiàn)蚁吝,當我重復定義了@ActionUnlockCheck
時旱爆,其實經過編譯后,字節(jié)碼class內部是這樣的:
@ActionUnlockChecks({@ActionUnlockCheck(
actionType = 114
), @ActionUnlockCheck(
actionType = 113
)})
也就是說多個子注解其實會被轉換成一個父注解灭将。