詳解@AliasFor注解的使用與注意事項(xiàng)
一、@AliasFor注解簡介
@AliasFor注解是在spring源碼當(dāng)中提供的,見名知義,他是為了別名而自定義的注解!
但這并不是java原生支持的,需要通過Spring中提供的工具類org.springframework.core.annotation.AnnotationUtils
或者org.springframework.core.annotation.AnnotatedElementUtils
來解析。AnnotatedElementUtils內(nèi)部還是調(diào)用的AnnotationUtils
二、使用場景
- 在注解中一對屬性上通過聲明@AliasFor,進(jìn)行屬性互換。
- 在注解上聲明了另一個(gè)注解,對另一個(gè)注解的屬性進(jìn)行別名覆蓋(也可以理解為將一個(gè)注解上的屬性值傳遞給另一個(gè)注解
三、 注意事項(xiàng)(重點(diǎn)關(guān)注)
指定別名,屬性互換的情況下,通過AnnotationUtils仍然可以獲取到值,而通過java原生的方式則無法獲取。 是因?yàn)镾pring其實(shí)是自己實(shí)現(xiàn)了jdk動(dòng)態(tài)的攔截器來實(shí)現(xiàn)別名功能. 但是: 如果同時(shí)設(shè)置,并且互為別名的兩個(gè)屬性值不一樣就會(huì)報(bào)錯(cuò),拋出如下異常:
Caused by: org.springframework.core.annotation.AnnotationConfigurationException: Different @AliasFor mirror values for annotation [com.sysmenu.annotion.MenuAuthCheck] declared on com.controller.ZnjProjectNoticeController.publishNoticeAnnouncement(com.dto.ZnjProjectNoticeAnnouncementInsertDTO); attribute 'permission' and its alias 'value' are declared with values of [lecture] and [lecture_report]. at org.springframework.core.annotation.AnnotationTypeMapping$MirrorSets$MirrorSet.resolve(AnnotationTypeMapping.java:711) at org.springframework.core.annotation.AnnotationTypeMapping$MirrorSets.resolve(AnnotationTypeMapping.java:666) at org.springframework.core.annotation.TypeMappedAnnotation.<init>(TypeMappedAnnotation.java:134) at org.springframework.core.annotation.TypeMappedAnnotation.<init>(TypeMappedAnnotation.java:118) at org.springframework.core.annotation.TypeMappedAnnotation.of(TypeMappedAnnotation.java:599) at org.springframework.core.annotation.MergedAnnotation.of(MergedAnnotation.java:610) at org.springframework.core.type.classreading.MergedAnnotationReadingVisitor.visitEnd(MergedAnnotationReadingVisitor.java:96)
所以互為別名,指定一個(gè)即可,兩個(gè)都會(huì)有相同的值
四、使用步驟
1.指定別名,屬性互換
1.1自定義注解
@Target({ElementType.TYPE, ElementType.METHOD}) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface MenuAuthCheck { @AliasFor("value") String permission() default ""; @AliasFor("permission") String value() default ""; }
1.2使用
@MenuAuthCheck("test_admin")
1.3注意事項(xiàng)
- 構(gòu)成別名對的每個(gè)屬性都必須用@AliasFor注釋,并且屬性或值必須引用別名對中的另一個(gè)屬性。
- 這兩個(gè)屬性的必須擁有相同的返回值類型。
- 別名屬性必須聲明默認(rèn)值。
- 這兩個(gè)屬性必須擁有相同的默認(rèn)值。
1.4 Spring中的@RequestMapping注解
我們通常直接使用
@RequestMapping("/web"")
value注解注釋也表明 這是 path的別名
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface RequestMapping { String name() default ""; /** * The primary mapping expressed by this annotation. * <p>This is an alias for {@link #path}. For example, * {@code @RequestMapping("/foo")} is equivalent to * {@code @RequestMapping(path="/foo")}. * <p><b>Supported at the type level as well as at the method level!</b> * When used at the type level, all method-level mappings inherit * this primary mapping, narrowing it for a specific handler method. * <p><strong>NOTE</strong>: A handler method that is not mapped to any path * explicitly is effectively mapped to an empty path. */ @AliasFor("path") String[] value() default {}; @AliasFor("value") String[] path() default {}; RequestMethod[] method() default {}; String[] params() default {}; String[] headers() default {}; String[] consumes() default {}; String[] produces() default {}; }
2.將一個(gè)注解上的屬性值傳遞給另一個(gè)注解對另一個(gè)注解的屬性進(jìn)行別名覆蓋
2.1舉例說明
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface TestAnnotation { @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @MyAnnotation public @interface TestAliasAnnotation { @AliasFor(annotation = TestAnnotation .class, attribute = "value") String name() default ""; }
將TestAliasAnnotation 注解中的name屬性傳遞給TestAnnotation 注解的value屬性,進(jìn)行覆蓋
2.2注意事項(xiàng)
被標(biāo)記@AliasFor的屬性和atttibute所指向的元注解屬性必須有相同的返回值類型。
3.組合多個(gè)注解,通過一個(gè)注解達(dá)到使用多個(gè)注解的效果
3.1 這是3個(gè)注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestAnnotation1 { String value(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestAnnotation2 { String name(); } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestAnnotation3 { String desc(); }
使用@AliasFor注解來定義一個(gè)新注解,將這三個(gè)注解組合起來如下:
3.2合并注解
/* * 合并注解 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @TestAnnotation1 @TestAnnotation2 @TestAnnotation3 public @interface TestMergeAnnotation { @AliasFor(annotation = TestAnnotation1 .class, attribute = "value") String value() default ""; @AliasFor(annotation = TestAnnotation2 .class, attribute = "name") String name() default ""; @AliasFor(annotation = TestAnnotation3 .class, attribute = "desc") String desc() default ""; }
在這個(gè)新注解中使用了@AliasFor注解,使一個(gè)注解達(dá)到同時(shí)使用3個(gè)注解的效果
3.3使用
@MyCombinedAnnotation(value = "perfect", name = "who", desc = "this is a merge annotation")
等價(jià)于三個(gè)注解同時(shí)使用
@TestAnnotation1 ("hello") @TestAnnotation2 (name = "world") @TestAnnotation3 (desc = "this is a merge annotation") public class TestClass { }
五、總結(jié)
- 我們在使用時(shí)這個(gè)注解時(shí),可以直接填寫內(nèi)容,而不用主動(dòng)指定"name"和"value"屬性,從而達(dá)到了隱示表明屬性別名的效果。
- 指定別名,屬性互換的情況下,通過AnnotationUtils仍然可以獲取到值,而通過java原生的方式則無法獲取。 是因?yàn)镾pring其實(shí)是自己實(shí)現(xiàn)了jdk動(dòng)態(tài)的攔截器來實(shí)現(xiàn)別名功能. 但是: 如果同時(shí)設(shè)置,并且互為別名的兩個(gè)屬性值不一樣就會(huì)報(bào)錯(cuò) 所以互為別名,指定一個(gè)即可,兩個(gè)都會(huì)有相同的值
作用
- 指定別名,屬性互換
- 將一個(gè)注解上的屬性值傳遞給另一個(gè)注解對另一個(gè)注解的屬性進(jìn)行別名覆蓋
- 組合多個(gè)注解,通過一個(gè)注解達(dá)到使用多個(gè)注解的效果
到此這篇關(guān)于詳解@AliasFor注解的使用與注意事項(xiàng)的文章就介紹到這了,更多相關(guān)@AliasFor注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入學(xué)習(xí)JavaWeb中監(jiān)聽器(Listener)的使用方法
這篇文章主要為大家詳細(xì)介紹了深入學(xué)習(xí)JavaWeb中監(jiān)聽器(Listener)的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Mybatis?Plus批處理操作的實(shí)現(xiàn)示例
MyBatis?Plus?提供了強(qiáng)大的批處理支持,可以幫助我們高效地處理大規(guī)模數(shù)據(jù),本文主要介紹了Mybatis?Plus批處理操作的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07MySQL 新增字段但 Java 實(shí)體未更新存在潛在問題與解決方案
在 Java + MySQL 的開發(fā)中,我們通常使用 ORM 框架(如 MyBatis、MyBatis-Plus、Hibernate)來映射數(shù)據(jù)庫表與 Java 對象,這篇文章主要介紹了MySQL 新增字段但 Java 實(shí)體未更新:潛在問題與解決方案,需要的朋友可以參考下2025-04-04idea在工具欄中顯示快速創(chuàng)建包和類的圖標(biāo)的詳細(xì)步驟
點(diǎn)擊需要?jiǎng)?chuàng)建包或者類的位置,在點(diǎn)擊對用的圖標(biāo)就可以快速創(chuàng)建類或者包了,下面小編給大家介紹idea在工具欄中顯示快速創(chuàng)建包和類的圖標(biāo)的詳細(xì)步驟,感興趣的朋友一起看看吧2024-02-02Java調(diào)用DOS實(shí)現(xiàn)定時(shí)關(guān)機(jī)的實(shí)例
Java調(diào)用DOS實(shí)現(xiàn)定時(shí)關(guān)機(jī)的實(shí)例,需要的朋友可以參考一下2013-04-04ApplicationListenerDetector監(jiān)聽器判斷demo
這篇文章主要為大家介紹了ApplicationListenerDetector監(jiān)聽器判斷demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03springboot版本升級以及解決springsecurity漏洞的問題
這篇文章主要介紹了springboot版本升級以及解決springsecurity漏洞的問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08