理解Java注解實作機制
前言
在Spring 2.0及早期時代,Java 還沒引入注解,這個時候如果我們要在 Spring 中宣告一個 Bean,我們只能通過 XML 配置的方式,Web專案開發都是通過組態檔 xml來實作 Bean 的依賴注入,有多少個Bean,就在xml配置中加多少個,這樣一來在 Bean 的數量越來越多的時候,xml的配置也就會越來越復雜,顯得格外的冗余,Spring 2.0 在xml組態檔上做了一定的優化,讓配置看起來越來越簡單,
而在后來的 Spring 3.0 時代,可以使用 Spring 提供的 Java 注解來取代曾經 xml 配置上的所產生的問題,Spring 使得專案開發配置變得簡單了許多
一,什么是注解?
.注解其實就是代碼里的特殊標記 ,這些標記可以在編譯,類加載,運行時被讀取,并執行相應的處理,通過使用注解,程式員可以在不改變原有邏輯的情況下 ,在源檔案中嵌入一些補充資訊,代碼分析工具,開發工具和部署工具可以通過這些補充資訊進行驗證或者進行部署
二, 注解有何用?
1,注解的出現極大的簡化了jdk1.5之前 使用xml配置的方式,代替JavaEE舊版中所遺留的繁冗代碼和XML配置等
2,生產檔案注解,標明該模塊類開發者,模塊版本等資訊,
3,在編譯時進行格式檢查(Jdk內置的三個基本注解)

4,跟蹤代碼依賴性,實作替代組態檔等功能
示例
xml配置方式
public class DemoService{
}
<bean id="demoService" class="com.lulu.DemoService"/>
注解配置方式
@Service
public class DemoService{
}
三,注解重要么?
未來的開發模式都是基于注解的,JPA是基于注解的,Spring2.5以上是基于注解的,現在的springboot是完全注解開發,注解是一種趨勢,一定程度上可以說:框架=注解+反射+設計模式,
四,如何自定義注解?
1:
在定義注解之前我們可以看看注解的原始碼是怎樣定義的
我們可以通過idea的快捷鍵選中注解 按住Crtl同時點擊滑鼠左鍵查看注解原始碼
如 選中select()上的 @Override
@Override
public List<Admin> select() {
return adminMapper.select();
}
}
2:
然后我們就看到了原始碼對@Override的定義,可以發現這和介面的定義很像,都有通過interface進行宣告,只不過interface多了一個@
還有兩個對注解的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
3:
然后我們可以參照此注解自定義注解,首先使用@interface關鍵字(自定義的注解自動繼承了java.lang.annotation.Annotation介面),我們可以給該注解加入一個成員引數屬性 value ,注意,雖然value有一對括號,和類,介面的方法定義很像 但它是注解的屬性不是方法
/**
* @author Tony-wang
* @create 2020-09-17-16:05
*/
public @interface MyAnnotation {
String value()
}
4:
然后我們就可以在其它類或方法上使用自定義注解了
注意 宣告注解成員后 如果沒有指定默認值default就要 在使用注解時 顯示的賦值 ,如果不宣告內部成員,那么該注解僅起到一個標識作用,如@Override就沒有內部成員
@MyAnnotation("hello")
public class Person{
五:元注解
1:什么是元注解呢?
元注解 是jdk中修飾其他注解的注解,jdk1.5中提供了4種標準的meta-annotation型別 分別是 Retention Target Document Inherited
Retention:只能用于修飾一個Annotation定義,用于指定該Annotation的生命周期,該元注解包含一個RetentionPolicy型別的成員變數,使用@Rentention必須為該value賦值
RetentionPolicy有三個狀態
RetentionPolicy.SOURCE:在源檔案中有效(編譯器直接丟棄這種策略的注釋)
RetentionPolicy.CLASS:在class檔案中有效,當運行java程式時,jvm不會保留注釋,這是默認值
RetentionPolicy.RUNTIME:在運行時有效(即運行中保留),當運行java程式時,jvm會保留注釋,程式可以通過反射獲取該注釋 *
Target 用于修飾該注解可以在哪些地方進行使用 指定類 中使用還是介面使用還是區域變數進行使用
如 該注解就只能在屬性和方法中使用
@Target({FIELD,METHOD})//表示該注解只能使用在屬性和方法上
@Retention(RetentionPolicy.RUNTIME)//運行時有效,被jvm類加載器加載到記憶體后 可以通過反射獲取注解資訊
public @ interface MyAnnotation{
Document :用于指定該注解會被javadoc 工具提取為檔案(很少用)
Inherited:被它修飾的注解具有基礎性(很少用)
Java 1.8中注解增強
元注解@Repeatable
元注解@Repeatable是JDK1.8新加入的,它表示在同一個位置重復相同的注解,在沒有該注解前,一般是無法在同一個型別上使用相同的注解的
//Java8前無法這樣使用
@FilterPath("/web/update")
@FilterPath("/web/add")
public class A {}
但在Java8新增了@Repeatable注解后就可以采用如下的方式定義并使用了
//使用Java1.8新增@Repeatable元注解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(FilterPaths.class)//引數指明接收的注解class
public @interface FilterPath {
String value();
}
//使用案例
@FilterPath("/web/add")
@FilterPath("/web/delete")
class AA{ }
JDK1.8新增兩個列舉成員
在Java8中 ElementType 新增兩個列舉成員,TYPE_PARAMETER 和 TYPE_USE ,在Java1.8前注解只能標注在一個宣告(如欄位、類、方法)上,Java8后,新增的TYPE_PARAMETER可以用于標注型別引數,而TYPE_USE則可以用于標注任意型別(不包括class),如下TYPE_USE修飾泛型型別,例外型別,強轉型別所示
@Target({FIELD,METHOD,TYPE_PARAMETER,TYPE_USE})//
@Retention(RetentionPolicy.RUNTIME)//運行時有效,被jvm類加載器加載到記憶體后 可以通過反射獲取注解資訊
public @ interface MyAnnotation{
string value() default "HEELO 靚仔!"
}
class Generic<@MyAnnotation T>{ //注解修飾泛型型別
public void show() throws @MyAnnotation RuntimeException{//注解修飾例外型別
ArrayList<@MyAnnotation String> list = new ArrayList<>();
int num = (@MyAnnotation int ) 10L;//對強轉型別進行修飾
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/83831.html
標籤:其他
上一篇:java Lambda 運算式
