日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

在我們的開發中,會不可避免的遇到Bean之間循環依賴的,所謂循環依賴,就是兩個或者兩個以上的Bean互相持有對方,這樣在程序運行調用中,會出現這種循環依賴的現象,假設是兩個Bean,當程序調用Bean A時,Bean A中依賴Bean B,在Bean A中調用Bean B時,Bean B中又依賴了Bean A,這樣就形成了循環依賴,如下圖:

Spring框架是怎么解決Bean之間的循環依賴的

 

先從一個小例子來說明,使用Spring框架如果出現循環依賴,會正常運行嗎?下例是在Spring Boot的基礎上構建的。

代碼結構如下:

Spring框架是怎么解決Bean之間的循環依賴的

 

程序訪問入口是HelloController,它里面調用了HelloService1:

package com.pig.employee.controller;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMApping;
import org.springframework.web.bind.annotation.RestController;
 
import com.pig.employee.service1.HelloService1;
 
@RestController
public class HelloController {
	
	@Autowired
	HelloService1 helloService1;
	
	@RequestMapping("/hello")
	public String sayHello() {
		return helloService1.say1();
	}
}

看一下HelloService1對應的實現類:

package com.pig.employee.service1.impl;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.pig.employee.service1.HelloService1;
import com.pig.employee.service2.HelloService2;
@Service("helloService1")
public class HelloService1Impl implements HelloService1 {
	
	@Autowired
	private HelloService2 helloService2;
	
	@Override
	public String say1() {
		System.out.println(helloService2.toString());
		return helloService2.say2();
	}
 
}

實現類中依賴了HelloService2,再來看一下HelloService2的實現類:

package com.pig.employee.service2.impl;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.pig.employee.service1.HelloService1;
import com.pig.employee.service2.HelloService2;
@Service("helloService2")
public class HelloService2Impl implements HelloService2 {
	
	@Autowired
	private HelloService1 helloService1;
	
	@Override
	public String say2() {
		System.out.println(helloService1.toString());
		return "helloService2 say hello";
	}
 
}

HelloService2的實現類中又依賴了HelloService1,這樣就形成了循環依賴,依托于Spring框架,這樣的循環依賴能運行成功嗎?廢話不多說,直接運行不就出答案了,啟動EmployeeApplication:

Spring框架是怎么解決Bean之間的循環依賴的

 

啟動沒有問題,再來訪問一下,瀏覽器輸入:http://localhost:8080/hello

Spring框架是怎么解決Bean之間的循環依賴的

 

成功訪問,再來看一下控制臺,兩個Bean也都已經實例化:

Spring框架是怎么解決Bean之間的循環依賴的

 

上面的簡單例子可以說明Spring框架可以解決Bean之間循環依賴的,下面就來探究Spring是怎么做到的?

對于Spring中Bean的管理,下圖一目了然:

Spring框架是怎么解決Bean之間的循環依賴的

 

先調用構造函數進行實例化,然后填充屬性,再接著進行其他附加操作和初始化,正是這樣的生命周期,才有了Spring的解決循環依賴,這樣的解決機制是根據Spring框架內定義的三級緩存來實現的,也就是說:三級緩存解決了Bean之間的循環依賴。我們從源碼中來說明。

先來看Spring中Bean工廠是怎么獲取Bean的(AbstractBeanFactory中):

Spring框架是怎么解決Bean之間的循環依賴的

 


Spring框架是怎么解決Bean之間的循環依賴的

 


Spring框架是怎么解決Bean之間的循環依賴的

 


Spring框架是怎么解決Bean之間的循環依賴的

 

一級一級向下尋找,找出了前面提到的三級緩存,也就是三個Map集合類:

singletonObjects:第一級緩存,里面放置的是實例化好的單例對象;

earlySingletonObjects:第二級緩存,里面存放的是提前曝光的單例對象;

singletonFactories:第三級緩存,里面存放的是要被實例化的對象的對象工廠。

所以當一個Bean調用構造函數進行實例化后,即使屬性還未填充,就可以通過三級緩存向外暴露依賴的引用值(所以循環依賴問題的解決也是基于JAVA的引用傳遞),這也說明了另外一點,基于構造函數的注入,如果有循環依賴,Spring是不能夠解決的。還要說明一點,Spring默認的Bean Scope是單例的,而三級緩存中都包含singleton,可見是對于單例Bean之間的循環依賴的解決,Spring是通過三級緩存來實現的。源碼是讓我們知其然并且知其所以然的最好參考,所以多多閱讀源碼!

分享到:
標簽:框架 Spring
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定