一、序言
SpringBoot 2.6.x
不推薦使用迴圈依賴,這是一個好訊息,SpringBoot從底層逐漸引導開發者書寫規範的程式碼,同時也是個憂傷的訊息,迴圈依賴的應用場景實在是太廣泛了。
如果從低版本升級到2.6.x
,那麼很大概率遇到的第一個問題便是迴圈依賴問題。
二、問題復原
1、程式碼說明
下面風格的程式碼比較普遍:兩個類都有呼叫對方方法的需求,因此很容易寫成迴圈引用。
@Service
public class TbDeptServiceImpl extends ServiceImpl<TbDeptMapper, TbDept> implements ITbDeptService {
@Autowired
private ITbStaffService staffService;
}
@Service
public class TbStaffServiceImpl extends ServiceImpl<TbStaffMapper, TbStaff> implements ITbStaffService {
@Autowired
private ITbDeptService deptService;
}
2、錯誤示例
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
Despite circular references being allowed, the dependency cycle between beans could not be broken. Update your application to remove the dependency cycle.
三、問題解決
1、粗暴解決
最簡單的方式是在全域性配置檔案中允許迴圈引用存在,此屬性預設值為false
,顯示宣告為true
,可迴避專案啟動時控制檯迴圈引用異常。
spring:
main:
allow-circular-references: true
2、優雅解決
Spring官方預設禁止使用迴圈依賴,儘管留有可選配置,允許開發者繼續使用迴圈依賴。
Spring官方的初心是不希望開發者編寫迴圈依賴的程式碼,也就是說未來的某個版本可能強制不得使用迴圈依賴,因此逐漸在新專案中消除迴圈依賴是不得不面對的問題。
使用方法的返回值獲取例項物件,替換通過成員變數注入例項物件。
@Service
public class TbDeptServiceImpl extends ServiceImpl<TbDeptMapper, TbDept> implements ITbDeptService {
/**
* 使用方法返回例項物件,替換成員變數注入
* @return ITbStaffService
*/
public ITbStaffService getStaffService(){
return SpringUtils.getBean(ITbStaffService.class);
}
}
@Service
public class TbStaffServiceImpl extends ServiceImpl<TbStaffMapper, TbStaff> implements ITbStaffService {
/**
* 使用方法返回例項物件,替換成員變數注入
* @return ITbStaffService
*/
public ITbDeptService getDeptService(){
return SpringUtils.getBean(ITbDeptService.class);
}
}
其中需要使用如下依賴,此依賴是筆者抽離出來的公共依賴
,可跨專案使用。
<dependency>
<groupId>xin.altitude.cms.common</groupId>
<artifactId>ucode-cms-common</artifactId>
<version>1.3.4</version>
</dependency>
如果找不到此依賴,很大可能是阿里雲Maven倉庫尚未同步,在專案中強制使用Maven中央倉庫即可。
<repositories>
<repository>
<id>public</id>
<name>maven nexus</name>
<url>https://repo1.maven.org/maven2/</url>
<snapshots>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
四、小結
Spring生態作為廣泛使用的框架,儼然成為Java企業級應用主流標準,其微小的變化對整合生態帶來不可估量的影響。從跟隨者轉化為引導者,果斷禁止迴圈依賴問題,體現的是作為引導者的擔當。
迴圈引用使用習慣了,初步看起來程式碼沒毛病,仔細想想是不合理的設計。迴圈依賴的直接表現是你中有我,我中有你
,從物件的設計上令人費解。
最為開發者時刻關注底層框架的變動,將會在應用層收益。這裡所說的底層框架是指JDK、Spring生態、Apache、知名大廠開源並廣泛被應用的框架,比如guava等。