本篇內(nèi)容主要講解“Bean的獲取過(guò)程是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Bean的獲取過(guò)程是什么”吧!
創(chuàng)新互聯(lián)公司云計(jì)算的互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)13年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、雅安服務(wù)器托管、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn),已先后獲得國(guó)家工業(yè)和信息化部頒發(fā)的互聯(lián)網(wǎng)數(shù)據(jù)中心業(yè)務(wù)許可證。專(zhuān)業(yè)提供云主機(jī)、雅安服務(wù)器托管、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
一、前言
二、面試題
三、Bean 的獲取過(guò)程
1. getBean 核心流程圖
2. getBean 從哪開(kāi)始讀源碼
3. getBean 源碼全局預(yù)覽
4. beanName 轉(zhuǎn)換操作
5. depends-on 依賴(lài) Bean
6. 處理單實(shí)例 Bean
7. 從緩存中獲取 bean 實(shí)例
8. FactoryBean 中獲取 bean 實(shí)例
四、測(cè)試案例
1. 別名
2. 依賴(lài)
3. BeanFactory
一、前言
你提出問(wèn)題,就要給出解決方案!
最近有粉絲小伙伴反饋,與自己的上級(jí)溝通總是遇到障礙,感覺(jué)不被理解。大部分時(shí)候他提出來(lái)的事情都可能會(huì)被領(lǐng)導(dǎo)說(shuō):“我沒(méi)get到你的點(diǎn)”、“你想做的這個(gè)項(xiàng)目沒(méi)有業(yè)務(wù)價(jià)值”、“你提出問(wèn)題,就要給出解決方案”,等等諸如此類(lèi)的回答。
鑒于具體情況要具體分析,可能我們并不一定能判斷出是誰(shuí)的問(wèn)題,導(dǎo)致在每次的交談中出現(xiàn)的分歧??赡苁莑eader有l(wèi)eader的苦衷和視角,也可能是員工有員工的理解和想法,所以最終沒(méi)有達(dá)成一致。
但就帶團(tuán)隊(duì)來(lái)講,有效溝通很重要。就像:如果你說(shuō)的都對(duì),那我為什么和你爭(zhēng)吵呢?與其壓制遇到的矛盾點(diǎn),不如都攤開(kāi)了聊,誰(shuí)的視角和心胸更大,誰(shuí)就多有一些同理心。
如果尖銳的批評(píng)完全消失,溫和的批評(píng)將會(huì)變得刺耳。
如果溫和的批評(píng)也不被允許,沉默將被認(rèn)為居心叵測(cè)。
如果沉默也不再允許,贊揚(yáng)不夠賣(mài)力將是一種罪行。
如果只允許一種聲音存在,那么,唯一存在的那個(gè)聲音就是謊言。
謝飛機(jī),小記!
,總感覺(jué) Spring 也沒(méi)啥看的,怎么面試官一問(wèn)就能問(wèn)出花?
面試官:Spring 的 getBean 中,transformedBeanName 的作用是什么?
謝飛機(jī):不知道呀,看單詞意思好像是改變Bean名稱(chēng)。
面試官:那這么說(shuō),你的 Bean 如果有 alias 別名,Spring 在獲取 Bean 時(shí)候要怎么處理?
謝飛機(jī):這!
面試官:那如果用了 depends-on 呢?
謝飛機(jī):啊, 我沒(méi)用過(guò) depends-on 我不知道!
面試官:那你調(diào)試代碼時(shí)候,看見(jiàn)過(guò)BeanName前面有 & 的情況嗎,為啥會(huì)出現(xiàn)?
謝飛機(jī):我不配知道!再見(jiàn)!
對(duì)于剛接觸看 Spring 源碼的伙伴來(lái)說(shuō),可能很疑惑于怎么就獲取一個(gè) Bean 就這么多流程呢?
所以,它為了適應(yīng)各類(lèi)的需求,變得越來(lái)越復(fù)雜了。而這部分知識(shí)的深入學(xué)習(xí)絕對(duì)不只是為了應(yīng)付八股文,更多的是考慮到在日常的 Spring 使用中遇到復(fù)雜問(wèn)題時(shí)有沒(méi)有一個(gè)大致知曉的流程,可以快速定位問(wèn)題,以及此類(lèi)需求的技術(shù)實(shí)現(xiàn)方案是否能在以后的應(yīng)用開(kāi)發(fā)中起到一定的指導(dǎo)作用,因?yàn)樗且环N設(shè)計(jì)方案的具體實(shí)現(xiàn)。
圖稿
,獲取。接下來(lái),我們就依次的把關(guān)于獲取 Bean 實(shí)例的重點(diǎn)代碼列舉出來(lái)做分析,讀者伙伴也可以結(jié)合流程圖一起看,這樣會(huì)更方便理解。
@Test
public void test_getBean() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
UserDao userDao = beanFactory.getBean("userDao", UserDao.class);
logger.info("獲取 Bean:{}", userDao);
}
beanFactory.getBean
的方式去獲取一個(gè) Bean 實(shí)例。源碼位置:AbstractBeanFactory -> getBean() -> doGetBean()
@Override
public T getBean(String name, Class requiredType) throws BeansException {
// getBean 就像你的領(lǐng)導(dǎo)其實(shí)沒(méi)做啥,都在 doGetBean 里
return doGetBean(name, requiredType, null, false);
}
protected T doGetBean(final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// 處理別名BeanName、處理帶&符的工廠(chǎng)BeanName
final String beanName = transformedBeanName(name);
Object bean;
// 先嘗試從緩存中獲取Bean實(shí)例,這個(gè)位置就是三級(jí)緩存解決循環(huán)依賴(lài)的方法
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 1. 如果 sharedInstance 是普通的 Bean 實(shí)例,則下面的方法會(huì)直接返回
// 2. 如果 sharedInstance 是工廠(chǎng)Bean類(lèi)型,則需要獲取 getObject 方法,可以參考關(guān)于 FactoryBean 的實(shí)現(xiàn)類(lèi)
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 循環(huán)依賴(lài)有三種,setter注入、多實(shí)例和構(gòu)造函數(shù),Spring 只能解決 setter 注入,所以這里是 Prototype 則會(huì)拋出異常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 1. 父 bean 工廠(chǎng)存在
// 2. 當(dāng)前 bean 不存在于當(dāng)前bean工廠(chǎng),則到父工廠(chǎng)查找 bean 實(shí)例
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 獲取 name 對(duì)應(yīng)的 beanName,如果 name 是以 & 開(kāi)頭,則返回 & + beanName
String nameToLookup = originalBeanName(name);
// 根據(jù) args 參數(shù)是否為空,調(diào)用不同的父容器方法獲取 bean 實(shí)例
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
// 1. typeCheckOnly,用于判斷調(diào)用 getBean 方法時(shí),是否僅是做類(lèi)型檢查
// 2. 如果不是只做類(lèi)型檢查,就會(huì)調(diào)用 markBeanAsCreated 進(jìn)行記錄
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 從容器 getMergedLocalBeanDefinition 獲取 beanName 對(duì)應(yīng)的 GenericBeanDefinition,轉(zhuǎn)換為 RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 檢查當(dāng)前創(chuàng)建的 bean 定義是否為抽象 bean 定義
checkMergedBeanDefinition(mbd, beanName, args);
// 處理使用了 depends-on 注解的依賴(lài)創(chuàng)建 bean 實(shí)例
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 監(jiān)測(cè)是否存在 depends-on 循環(huán)依賴(lài),若存在則會(huì)拋出異常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注冊(cè)依賴(lài)記錄
registerDependentBean(dep, beanName);
try {
// 加載 depends-on 依賴(lài)(dep 是 depends-on 縮寫(xiě))
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 創(chuàng)建單例 bean 實(shí)例
if (mbd.isSingleton()) {
// 把 beanName 和 new ObjectFactory 匿名內(nèi)部類(lèi)傳入回調(diào)
sharedInstance = getSingleton(beanName, new ObjectFactory
綜上基本就是 getBean 過(guò)程涉及到的核心處理方法,基本包括;
處理 & 符:transformedBeanName() -> BeanFactoryUtils.transformedBeanName(name)
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
String beanName = name;
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
return beanName;
}
(String FACTORY_BEAN_PREFIX = "&")
&&&userService -> &&userService -> &userService -> userService
別名轉(zhuǎn)換:transformedBeanName() -> canonicalName
public String canonicalName(String name) {
String canonicalName = name;
// Handle aliasing...
String resolvedName;
do {
resolvedName = this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
}
while (resolvedName != null);
return canonicalName;
}
AbstractBeanFactory -> isDependent(beanName, dep) -> DefaultSingletonBeanRegistry
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
private boolean isDependent(String beanName, String dependentBeanName, Set alread
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
String canonicalName = canonicalName(beanName);
Set dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet();
}
alreadySeen.add(beanName);
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
AbstractBeanFactory -> registerDependentBean(dep, beanName) -> DefaultSingletonBeanRegistry
public void registerDependentBean(String beanName, String dependentBeanName) {
String canonicalName = canonicalName(beanName);
synchronized (this.dependentBeanMap) {
Set dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
dependentBeans = new LinkedHashSet(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
}
dependentBeans.add(dependentBeanName);
}
synchronized (this.dependenciesForBeanMap) {
Set dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName
if (dependenciesForBean == null) {
dependenciesForBean = new LinkedHashSet(8);
this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);
}
dependenciesForBean.add(canonicalName);
}
}
最后:getBean(dep),就可以獲取到 depends-on 依賴(lài)的 Bean 了
AbstractBeanFactory -> mbd.isSingleton()
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
doCreateBean -> if (earlySingletonExposure) -> getSingleton(beanName, false)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 從 singletonObjects 獲取實(shí)例,singletonObjects 中緩存的實(shí)例都是完全實(shí)例化好的 bean,可以直接使用
Object singletonObject = this.singletonObjects.get(beanName);
// 如果 singletonObject 為空,則沒(méi)有創(chuàng)建或創(chuàng)建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 加鎖
synchronized (this.singletonObjects) {
// 單例緩存池中,沒(méi)有當(dāng)前beanName
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 加入到三級(jí)緩存,暴漏早期對(duì)象用于解決三級(jí)緩存
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
AbstractBeanFactory -> getObjectForBeanInstance(sharedInstance, name, beanName, null)
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 如果 beanName 以 & 開(kāi)頭,但 beanInstance 卻不是 FactoryBean,則會(huì)拋出異常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 這里判斷就是這個(gè) bean 是不是 FactoryBean,不是就直接返回了
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 如果 mbd 為空,則從緩存加載 bean(FactoryBean 生成的單例 bean 實(shí)例會(huì)緩存到 factoryBeanObjectCache 集合中,方便使用)
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 到這,beanInstance 是 FactoryBean 類(lèi)型,所以就強(qiáng)轉(zhuǎn)了
FactoryBean> factory = (FactoryBean>) beanInstance;
// mbd 為空且判斷 containsBeanDefinition 是否包含 beanName
if (mbd == null && containsBeanDefinition(beanName)) {
// 合并 BeanDefinition
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 調(diào)用 getObjectFromFactoryBean 獲取實(shí)例
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
@Test
public void test_alias() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-alias.xml");
UserService userService = beanFactory.getBean("userService-alias02", UserService.class);
logger.info("獲取 Bean 通過(guò)別名:{}", userService);
}
@Test
public void test_depends_on() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-depends-on.xml");
UserService userService = beanFactory.getBean(UserService.class, "userService");
logger.info("獲取 Bean:{}", userService.getUserDao());
}
@Test
public void test_factory_bean() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config-factory-bean.xml");
UserDao userDao = beanFactory.getBean("userDao", UserDao.class);
logger.info("獲取 Bean:{}", userDao);
}
到此,相信大家對(duì)“Bean的獲取過(guò)程是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!