Spring 的組合註解功能,網上有不少文章介紹,不過都是介紹其使用方法,鮮有其原理解析。java
組合註解並不是 Java 的原生能力。就是說,想經過用「註解A」來註解「註解B」,再用「註解B」 來註解 C(類或方法),就可以使 C 同時擁有「註解A」和「註解B」是行不通的。ide
示例以下:測試
先定義註解 SuperAnno:spa
import java.lang.annotation.*; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SuperAnno { }
再定義註解 SubAnno,並使用 SuperAnno 註解 SubAnno:code
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SuperAnno @SomeAnno public @interface SubAnno { }
定義 Test,使用 SubAnno 註解 Test:blog
@SubAnno public class Test { }
測試一下,看看咱們能不能拿到 Test 的 SuperAnno 註解:遞歸
import java.lang.annotation.Annotation; public class Main { public static void main(String[] args) { // write your code here Test test = new Test(); Class<?> cl = test.getClass(); Annotation[] annotations = cl.getAnnotations(); for(Annotation annotation: annotations) { System.out.println(annotation.annotationType()); } } }
打印出來的結果爲:get
interface com.company.SubAnno
唔,SuperAnno 沒有出現。it
怎麼拿到合併的註解呢?io
核心的思路就是拿到註解後,遞歸獲取其上的註解,見下例:
import javax.annotation.*; import java.lang.annotation.*; import java.util.ArrayList; public class Main { private ArrayList<Annotation> annos = new ArrayList<>(); public static void main(String[] args) { // write your code here Test test = new Test(); Class<?> cl = test.getClass(); Main main = new Main(); main.getAnnos(cl); for(Annotation anno: main.annos) { System.out.println(anno.annotationType()); } } private void getAnnos(Class<?> cl) { Annotation[] annotations = cl.getAnnotations(); for(Annotation annotation: annotations) { if (annotation.annotationType() != Deprecated.class && annotation.annotationType() != SuppressWarnings.class && annotation.annotationType() != Override.class && annotation.annotationType() != PostConstruct.class && annotation.annotationType() != PreDestroy.class && annotation.annotationType() != Resource.class && annotation.annotationType() != Resources.class && annotation.annotationType() != Generated.class && annotation.annotationType() != Target.class && annotation.annotationType() != Retention.class && annotation.annotationType() != Documented.class && annotation.annotationType() != Inherited.class ) { annos.add(annotation); getAnnos(annotation.annotationType()); } } } }