程式設計師應知應會之Spring Data Jpa為什麼不用寫@Repository註解?

大家知道,在Springboot+Spring Data Jpa的專案裡,dao層只需要繼承JpaRepository介面,就可以實現Mybatis中@Repository+mapper的效果,不需要任何多餘的配置,就可以將dao層注入bean。類似於這樣:

publicinterface

BookRepository

extends

JpaRepository

這樣一句話,就可以實現很多的增刪改查效果,例如findAll,findById等等,可以說是非常的簡單高效。

那麼很多剛開始用Spring Data Jpa的同學就會很不理解,為什麼這樣一句話,就可以實現那麼多的功能呢,不新增一個@Repository,心裡總有些不踏實的感覺。

那麼我們來看一下,Spring Data Jpa是怎麼做到的。

一、JpaRepository的繼承結構

首先我們來看看JpaRepository的繼承結構。很容易看到JpaRepository的定義:

publicinterface

JpaRepository

extends

PagingAndSortingRepository

, QueryByExampleExecutor

可以看到JpaRepository繼承了兩個介面,一個

PagingAndSortingRepository和一個QueryByExampleExecutor。

這兩個介面的定義分別是:

publicinterface

PagingAndSortingRepository

extends

CrudRepository

publicinterface

QueryByExampleExecutor

CrudRepository的定義為

publicinterface

CrudRepository

extends

Repository

可以看到,最終的繼承結果繼承到了Repository裡面。

而這一系列的繼承,就為我們提供了

save(Sentity);

saveAll(Iterable

entities);

findById(IDid);

existsById(IDid);

findAll;

findAllById(Iterable

ids);

count;

deleteById(IDid);

delete(Tentity);

deleteAll(Iterable

extends

T>entities);

deleteAll;

findOne(Example

example);

findAll(Example

example);

findAll(Example

example, Sortsort);

findAll(Example

example, Pageablepageable);

count(Example

example);

exists(Example

example);

findAll(Sortsort);

findAll(Pageablepageable);

等很多的功能。

二、JpaRepository為什麼不需要@Repository註解

經過簡單的Debug,我們就可以輕鬆定位到Spring注入bean的位置,是在

org。springframework。context。annotation包裡面的

ClassPathScanningCandidateComponentProvider類中的

scanCandidateComponents方法裡面,其中關鍵的程式碼在下面標藍的

isCandidateComponent(metadataReader)判斷裡面。

程式設計師應知應會之Spring Data Jpa為什麼不用寫@Repository註解?

而這個函式會將目標介面及其父介面一層層地往上對比,如果與該類自身的

includeFilters中的某個filter比中,則會返回true,意味著該實現將會作為bean被Spring管理起來,從而可以直接用@Autowired引用。

那麼我們先來看看includeFilters裡面到底有些什麼東西,查詢程式碼可以看到,該類在初始化的時候,添加了Component和ManagedBean。很顯然,這與我們的Repository還是毫無關係的。事實上也是如此,在Spring啟動時,第一遍掃描並沒有把我們的BookRepository注入bean。

直到

org。springframework。data。repository。config包中的

RepositoryConfigurationDelegate執行的時候,才會開始掃描,而這個類執行的時候,會啟動一個繼承了ClassPathScanningCandidateComponentProvider類的RepositoryComponentProvider。

而在這個類裡面,我們可以看到Repository最終被載入到了includeFilters裡面。

程式設計師應知應會之Spring Data Jpa為什麼不用寫@Repository註解?

此時,再掃描對應的包的時候,繼承自Repository的所有dao層類,就被會注入成bean,供人們呼叫了。

喜歡本文的話,歡迎關注活在資訊時代哦:)