程式設計師應知應會之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)判斷裡面。
而這個函式會將目標介面及其父介面一層層地往上對比,如果與該類自身的
includeFilters中的某個filter比中,則會返回true,意味著該實現將會作為bean被Spring管理起來,從而可以直接用@Autowired引用。
那麼我們先來看看includeFilters裡面到底有些什麼東西,查詢程式碼可以看到,該類在初始化的時候,添加了Component和ManagedBean。很顯然,這與我們的Repository還是毫無關係的。事實上也是如此,在Spring啟動時,第一遍掃描並沒有把我們的BookRepository注入bean。
直到
org。springframework。data。repository。config包中的
RepositoryConfigurationDelegate執行的時候,才會開始掃描,而這個類執行的時候,會啟動一個繼承了ClassPathScanningCandidateComponentProvider類的RepositoryComponentProvider。
而在這個類裡面,我們可以看到Repository最終被載入到了includeFilters裡面。
此時,再掃描對應的包的時候,繼承自Repository的所有dao層類,就被會注入成bean,供人們呼叫了。
喜歡本文的話,歡迎關注活在資訊時代哦:)