SpringBoot2.6.x預設禁用迴圈依賴後的應對策略

Java知識圖譜發表於2022-02-23

一、序言

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等。

相關文章