【面試必問】Java經常使用註解及原理

註解是什麼?

Java 註解是Java5添加的,用於爲 Java 代碼提供元數據。做爲元數據,註解不直接影響你的代碼執行,但也有一些類型的註解能夠用於這一目的。java

註解是一種元數據,能夠將它理解爲一種特殊的註釋,它爲咱們在代碼中添加信息提供了一種形式化的方法,它用於幫助咱們更快捷的寫代碼。spring

簡單來講,註解主要有四個部分的做用編程

  • 生成文檔:即將元數據生成爲Javadoc文檔;
  • 編譯檢查:編譯器在編譯階段會對代碼進行檢查,例如@override註解會提示編譯器查看其是否重寫了父類的方法;
  • 編譯動態處理:主要是用做動態生成代碼,例如一些幫助類、方法,經過註解實現自動生成;
  • 運行動態處理:典型的例子是使用反射來注入實例;

Java提供了三種註解:自帶的標準註解(見下)、元註解(指修飾註解的註解,是最基準的註解)、自定義註解(用戶能夠自定義註解,如@Retention、@Target、@Inherited、@Documented、@Repeatable 等)markdown

在實際的項目開發中見到的註解通常是來自Java自帶的註解、元註解、Spring等框架的註解(如@Resource、@Bean等,lombok的@data、@Slf4j等)。框架

常見註解

一些Java及Spring等常見的註解以下:ide

  1. @Deprecated – 所標註內容再也不被建議使用;
  2. @Override – 只能標註方法,表示該方法覆蓋父類中的方法;
  3. @SuppressWarnings – 所標註內容產生的警告,編譯器會對這些警告保持靜默;
  4. @interface用於定義一個註解
  5. @Documented --將所標註內容包含到javadoc中;
  6. @Inherited – 只能被用來標註「Annotation類型」,它所標註的Annotation具備繼承性,跟類的繼承形式贊成;
  7. @Retention – 只能被用來標註「Annotation類型」,並且它被用來指定Annotation的RetentionPolicy屬性,它表示註解存在階段是保留在源碼(編譯期),字節碼(類加載)或者運行期(JVM中運行),關於註解聲明週期的概念能夠看看下圖:

img

通常來講,若是retention設置爲source和class,那麼就須要被繼承並實現,由於加載到JVM時,這二者的註解就被抹除了,也就失去了效果。(lombok的@Data註解就是在這個過程當中,加入了get/set方法)函數

  1. @Target – 只能被用來標註「Annotation類型」,並且它被用來指定Annotation的ElementType屬性,它是經過枚舉類類來表示註解的做用範圍,如做用於TYPE(接口、類、枚舉、註解)、FIELD(字段、枚舉常量)、METHOD(方法)、PARAMETER(方法參數)、ANNOTATION_TYPE(註解)、CONSTRUCTOR(構造函數)、LOCAL_VARIABLE(局部變量)、PACKAGE(包)等
  2. @Repeatable-代表該註解所修飾的註解能夠同時做用一個對象屢次,但每次的含義能夠不一樣;

下面是Spring的一些重要註解:oop

  1. @Configuration

標註在類上,至關於把該類做爲spring的xml配置文件中的,用來配置spring容器(上下文)。spa

  1. @Bean

標註在方法上(返回某個實例的方法),等價於spring的xml配置文件中的,做用爲:註冊bean對象。@Bean註解默認做用域爲單例singleton做用域。.net

  1. @ComponentScan

標註在類上,用於對Component進行掃描;

  1. @WishlyConfiguration

組合註解,能夠替代註解2-3;

上述1-4,是配置類的相關注解;

  1. @Component

通常是在類上,代表其是一個組件,告知Spring該類會建立Bean;

  1. @Repository

代表該對象是數據訪問層(DAO)使用的;

  1. @Service

代表該對象是業務邏輯層(SERVICE)使用的;

  1. @Controller

這是控制器的聲明,代表該對象在展示層使用;

以上5-8都是有關聲明bean的註解;

  1. @Resource:自動依賴注入

  2. @Autowired:自動依賴注入;

注:二者的用法很類似,都是用做依賴注入,可是Resource是默認按照Name注入,而Autowired是按照Type注入的

  1. @Inject:手動依賴注入;

這裏補充一下Spring啓動容器與組件之間的具體過程:

  • 在啓動spring的時候,首先要啓動容器
  • 啓動spring容器時,會默認尋找容器掃描範圍內的可加載bean,而後查找哪些bean上的屬性和方法上有@Resource註解
  • 找到@Resource註解後,判斷@Resource註解括號中的name屬性是否爲空,若是爲空:看spring容器中的bean的id與@Resource要註解的那個變量屬性名是否相同,如相同,匹配成功;若是不相同,看spring容器中bean的id對應的類型是否與@Resource要註解的那個變量屬性對應的類型是否相等,若相等,匹配成功,若不相等,匹配失敗;
  • 若是@Resource註解括號中的name屬性不爲空,看name的屬性值和容器中的bean的id名是否相等,如相等,則匹配成功;如不相等,則匹配失敗。

其餘一些註解以下:

  1. @profile

指定類或方法在特定的 Profile 環境生效,任何@Component或@Configuration註解的類均可以使用@Profile註解。在使用DI來依賴注入的時候,可以根據@profile標明的環境,將注入符合當前運行環境的相應的bean。

  1. @Data :注在類上,提供類的get、set、equals、hashCode、canEqual、toString方法

  2. @AllArgsConstructor :注在類上,提供類的全參構造

  3. @NoArgsConstructor :注在類上,提供類的無參構造

  4. @Setter : 注在屬性上,提供 set 方法;

  5. @Getter :注在屬性上,提供 get 方法

  6. @EqualsAndHashCode :注在類上,提供對應的 equals 和 hashCode 方法;

  7. @Log4j/@Slf4j : 注在類上,提供對應的 Logger 對象,變量名爲 log

  8. @After: 代表該方法在其餘方法執行以後執行;

  9. @Before: 代表該方法在其餘方法執行以前執行;

  10. @Around: 代表該方法在其餘方法執行以前和以後都執行;

自定義註解?

上述的這些常見的註解能夠減小代碼量,使得代碼結構更加簡潔和清晰,可是光用這些註解是不夠的,有時在業務場景須要或者保持代碼結構清晰等狀況下,就須要使用自定義註解了。

舉個例子,通常項目中都要設置日誌系統,或是監控告警系統,就須要上傳或者提供一些QPS、RT等,若是將這些代碼直接寫在項目代碼中,那麼就會使得項目代碼被污染,並且,在項目中會大量存在這些重複代碼,這個時候自定義註解就有用咯!

如何解?那就是利用APO切面編程以及反射的思想!將AOP相關的配置信息寫入註解裏,就能夠實現優雅地解決這個問題了。

反射是爲了獲取Java運行時的相關信息,AOP切面編程是爲了可以在Spring的AOP中中直接判斷某一個方法是否帶有自定義的註解——若是有,那麼自定義註解就會將相關的監控邏輯加載在相關的方法上。

有關這個案例,能夠詳細看一下這篇博客結尾的代碼

參考資料

常見註解

Java自定義註解

Java3y寫的註解,很棒

相關文章
相關標籤/搜索