宅男在线永久免费观看网直播,亚洲欧洲日产国码无码久久99,野花社区在线观看视频,亚洲人交乣女bbw,一本一本久久a久久精品综合不卡

全部
常見問題
產品動態(tài)
精選推薦

解決循環(huán)依賴的方法

管理 管理 編輯 刪除

一、什么是循環(huán)依賴呢?

類A依賴類B,類B也依賴類A,這種情況就會出現(xiàn)循環(huán)依賴。

Bean A → Bean B → Bean A

上面是比較容易發(fā)現(xiàn)的循環(huán)依賴,也有更深層次的循環(huán)依賴。

Bean A → Bean B → Bean C → Bean D → Bean E → Bean A

二、Spring 的循環(huán)依賴

當Spring上下文在加載所有的bean時,會嘗試按照他們他們關聯(lián)關系的順序進行創(chuàng)建。如果不存在循環(huán)依賴時,例如:

Bean A → Bean B → Bean C

Spring會先創(chuàng)建Bean C,再創(chuàng)建Bean B(并將Bean C注入到Bean B中),最后再創(chuàng)建Bean A(并將Bean B注入到Bean A中)。

但是,如果我們存在循環(huán)依賴,Spring上下文不知道應該先創(chuàng)建哪個Bean,因為它們依賴于彼此。在這種情況下,Spring會在加載上下文時,拋出一個BeanCurrentlyInCreationException

當我們使用構造方法進行注入時,會遇到這種情況。因為它是上下文加載就被要求注入。

三、舉個栗子

用戶類需要調用組織類中的方法,于是通過構造方法注入組織類。

@Service
public class UserService {
    
    private final DepartmentService departmentSerivce;
 
    /**
     * 通過構造方法注入DepartmentService類
     */
    @Autowired
    public UserSerivce(DepartmentService departmentService) {
        this.departmentService = departmentService;
    }
 
    public List<Department> list() {
        retern departmentService.list();
    }    
 
}

而組織類也剛好需要調用用戶類里的方法,于是它也通過構造方法注入用戶類。

@Service
public class DepartmentService {
    
    private final UserService userSerivce;
 
    /**
     * 通過構造方法注入UserService類
     */
    @Autowired
    public DepartmentSerivce(UserService userSerivce) {
        this.userSerivce = userSerivce;
    }
    
}

這種情況程序在編譯時,就會報下面的錯誤

Description:
 
The dependencies of some of the beans in the application context form a cycle:
 
┌─────┐
|  userService defined in file [D:\Java\IdeaProjects\UserService.class]
↑     ↓
|  departmentService defined in file [D:\Java\IdeaProjects\DepartmentService.class]
└─────┘

現(xiàn)在我們可以為測試編寫一個配置類,讓我們稱之為??TestConfig??,它指定要掃描組件的基本包。讓我們假設我們的bean在包"??com.baeldung.circulardependency??"中定義:?

@Configuration
@ComponentScan(basePackages = { "com.baeldung.circulardependency" })
public class TestConfig {
}

最后,我們可以編寫一個 JUnit 測試來檢查循環(huán)依賴關系。測試可以為空,因為在上下文加載期間將檢測到循環(huán)依賴關系。?

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyTest {
 
    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // Empty test; we just want the context to load
    }
}

如果您嘗試運行此測試,您將得到以下異常:?

BeanCurrentlyInCreationException: Error creating bean with name 'UserService':
Requested bean is currently in creation: Is there an unresolvable circular reference?

四、解決辦法

4.1 重新設計

當出現(xiàn)這種循環(huán)依賴時,很可能是在設計方面存在問題,沒有把每個類的職責很好的區(qū)分開。應該嘗試正確重新設計組件,以便其層次結構設計良好,并且不需要循環(huán)依賴項。?

如果無法重新設計,那么可以考慮其他解決辦法。


4.2 使用 setter/field 方法注入

上面說到,只有構造方法是在上下文加載時就要求被注入,容易出現(xiàn)依賴循環(huán)。所以可以用其他的方式進行依賴注入,setter 和 field 方法注入與構造方法不同,它們不會在創(chuàng)Bean時就注入依賴,而是在被需要時才注入。

setter方法注入

@Service
public class UserService {
    
    private DepartmentService departmentSerivce;
 
   
    @Autowired
    public void setDepartmentSerivce(DepartmentService departmentService) {
        this.departmentService = departmentService;
    }
 
    public List<Department> list() {
        retern departmentService.list();
    }    
 
}

另一個類也是同理使用setter方法注入

field方法注入

(使用@Autowired)

@Service
public class UserService {
    
    @Autowired
    private DepartmentService departmentSerivce;
 
 
    public List<Department> list() {
        retern departmentService.list();
    }    
 
}

4.3 使用 @Lazy

解決Spring 循環(huán)依賴的一個簡單方法就是對一個Bean使用延時加載。也就是說:這個Bean并沒有完全的初始化完,實際上他注入的是一個代理,只有當他首次被使用的時候才會被完全的初始化。
我們對 UserService 進行修改,結果如下:

@Service
public class UserService {
    
    private DepartmentService departmentSerivce;
 
    @Autowired
    public UserSerivce(@Lazy DepartmentService departmentService) {
        this.departmentService = departmentService;
    }
 
    public List<Department> list() {
        retern departmentService.list();
    }    
 
}

如果你現(xiàn)在運行測試,你會發(fā)現(xiàn)之前的錯誤不存在了。

4.4 使用 @PostConstruct

打破循環(huán)的另一種方式是,在要注入的屬性(該屬性是一個bean)上使用 @Autowired,并使用@PostConstruct 標注在另一個方法,且該方法里設置對其他的依賴。

我們的Bean將修改成下面的代碼:

@Service
public class UserService {
 
    @Autowired
    private DepartmentService departmentService;
 
    @PostConstruct
    public void init() {
        departmentService.setUserService(this);
    }
 
    public DepartmentService getDepartmentService() {
        return departmentService;
    }
}
@Service
public class DepartmentService {
 
    private UserService userService;
     
    private String message = "Hi!";
 
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
     
    public String getMessage() {
        return message;
    }
}

現(xiàn)在我們運行我們修改后的代碼,發(fā)現(xiàn)并沒有拋出異常,并且依賴正確注入進來。

4.5 實現(xiàn)ApplicationContextAware and InitializingBean接口

如果一個Bean實現(xiàn)了ApplicationContextAware,該Bean可以訪問Spring上下文,并可以從那里獲取到其他的bean。實現(xiàn)InitializingBean接口,表明這個bean在所有的屬性設置完后做一些后置處理操作(調用的順序為init-method后調用);在這種情況下,我們需要手動設置依賴。

@Service
public class UserService implements ApplicationContextAware, InitializingBean {
 
    private DepartmentService departmentService;
 
    private ApplicationContext context;
 
    public DepartmentService getDepartmentService() {
        return departmentService;
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        circB = context.getBean(DepartmentService.class);
    }
 
    @Override
    public void setApplicationContext(final ApplicationContext ctx) throws BeansException {
        context = ctx;
    }
}
public class DepartmentService {
 
    private UserService userService;
 
    private String message = "Hi!";
 
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
 
    public String getMessage() {
        return message;
    }
}

同樣,我們可以運行之前的測試,看看有沒有異常拋出,程序結果是否是我們所期望的那樣。

4.6 其他辦法

我遇到的這個問題的情況,是 Service 之間互相依賴導致了深層次的循環(huán)依賴。但是我真正想調用的是 Mybatis Plus 提供的基礎方法,所以可以將依賴 Service 換成依賴 Mapper,因為 Mapper 中也有這些基礎方法。

@Service
public class UserService {
    
    private final DepartmentMapper departmentMapper;
 
    @Autowired
    public UserSerivce(DepartmentMapper departmentMapper) {
        this.departmentMapper = departmentMapper;
    }
 
    public List<Department> list() {
        retern departmentMapper.selectList();
    }    
 
}

五、總結

?在Spring中,有很多方法可以處理循環(huán)依賴關系。首先要考慮的是重新設計你的bean,這樣就不需要循環(huán)依賴關系:它們通常是可以改進的設計的癥狀。??但是,如果您絕對需要在項目中具有循環(huán)依賴項,則可以按照此處建議的一些解決方法進行操作。


請登錄后查看

CRMEB-慕白寒窗雪 最后編輯于2023-03-06 11:07:33

快捷回復
回復
回復
回復({{post_count}}) {{!is_user ? '我的回復' :'全部回復'}}
排序 默認正序 回復倒序 點贊倒序

{{item.user_info.nickname ? item.user_info.nickname : item.user_name}} LV.{{ item.user_info.bbs_level || item.bbs_level }}

作者 管理員 企業(yè)

{{item.floor}}# 同步到gitee 已同步到gitee {{item.is_suggest == 1? '取消推薦': '推薦'}}
{{item.is_suggest == 1? '取消推薦': '推薦'}}
沙發(fā) 板凳 地板 {{item.floor}}#
{{item.user_info.title || '暫無簡介'}}
附件

{{itemf.name}}

{{item.created_at}}  {{item.ip_address}}
打賞
已打賞¥{{item.reward_price}}
{{item.like_count}}
{{item.showReply ? '取消回復' : '回復'}}
刪除
回復
回復

{{itemc.user_info.nickname}}

{{itemc.user_name}}

回復 {{itemc.comment_user_info.nickname}}

附件

{{itemf.name}}

{{itemc.created_at}}
打賞
已打賞¥{{itemc.reward_price}}
{{itemc.like_count}}
{{itemc.showReply ? '取消回復' : '回復'}}
刪除
回復
回復
查看更多
打賞
已打賞¥{{reward_price}}
1591
{{like_count}}
{{collect_count}}
添加回復 ({{post_count}})

相關推薦

快速安全登錄

使用微信掃碼登錄
{{item.label}} 加精
{{item.label}} {{item.label}} 板塊推薦 常見問題 產品動態(tài) 精選推薦 首頁頭條 首頁動態(tài) 首頁推薦
取 消 確 定
回復
回復
問題:
問題自動獲取的帖子內容,不準確時需要手動修改. [獲取答案]
答案:
提交
bug 需求 取 消 確 定
打賞金額
當前余額:¥{{rewardUserInfo.reward_price}}
{{item.price}}元
請輸入 0.1-{{reward_max_price}} 范圍內的數(shù)值
打賞成功
¥{{price}}
完成 確認打賞

微信登錄/注冊

切換手機號登錄

{{ bind_phone ? '綁定手機' : '手機登錄'}}

{{codeText}}
切換微信登錄/注冊
暫不綁定
CRMEB客服

CRMEB咨詢熱線 咨詢熱線

400-8888-794

微信掃碼咨詢

CRMEB開源商城下載 源碼下載 CRMEB幫助文檔 幫助文檔
返回頂部 返回頂部
CRMEB客服