Spring中Bean注入源碼示例解析
BeanDefinition和Bean
在Spring中Bean的注入涉及兩部分:
- BeanDefinition
- Bean
兩個(gè)對(duì)象存在先后順序,先注入BeanDefinition之后才執(zhí)行Bean對(duì)象的注入。
那么兩者有什么關(guān)聯(lián)呢?
BeanDefinition和Bean的關(guān)系:可以理解為BeanDefinition是Bean的包裝類,類似Java中類和屬性的關(guān)系。
BeanDefinition是對(duì)Bean對(duì)象的包裝,BeanDefinition中封裝了Bean相關(guān)的描述,比如bean對(duì)象,bean的單例還是原型、bean的父級(jí)、懶加載方式等等。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { void setScope(@Nullable String scope); @Nullable String getScope(); void setLazyInit(boolean lazyInit); boolean isLazyInit(); } //bean的原數(shù)據(jù) public interface BeanMetadataElement { @Nullable Object getSource(); }
在BeanDefinition中繼承了BeanMetadataElement,該類是Bean的原數(shù)據(jù),該類中實(shí)例化了Bean對(duì)象為Object。因此在BeanDefinition中調(diào)用getSource就可以獲取到Bean對(duì)象。
分清楚BeanDefinition和Bean之后再看BeanDefinition的注入,因?yàn)橹挥凶⑷肓薆eanDefinition才會(huì)注入后續(xù)的Bean。
BeanDefinition的注入
BeanDefinitionRegistry接口
BeanDefinitin的注入通過(guò)接口BeanDefinitionRegistry抽象了各種對(duì)BeanDefinition的操作,例如
- BeanDefinitionRegistry#registerBeanDefinition(注入到beanDefinition中)
- BeanDefinitionRegistry#removeBeanDefinition(從beanDefinition容器中移除)
- BeanDefinitionRegistry#getBeanDefinition(獲取BeanDefinition)
public interface BeanDefinitionRegistry extends AliasRegistry { void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; boolean containsBeanDefinition(String beanName); String[] getBeanDefinitionNames(); int getBeanDefinitionCount(); boolean isBeanNameInUse(String beanName); }
該接口是操作BeanDefinition的基礎(chǔ)接口,該類是一個(gè)接口類型并不是一個(gè)抽象類,因此該接口中不會(huì)定義任何BeanDefinition的容器,BeanDefinition的容器只在各實(shí)現(xiàn)類中定義并使用。任何需要操作BeanDefinition的實(shí)現(xiàn)都需要實(shí)現(xiàn)該接口。
BeanDefinitionRegistry的實(shí)現(xiàn)類
找到操作BeanDefinition的接口就可以通過(guò)接口查看接口的實(shí)現(xiàn)類,進(jìn)而找到BeanDefinition的應(yīng)用。
BeanDefinition常見(jiàn)的幾個(gè)實(shí)現(xiàn)類有:
- DefaultListableBeanFactory
- SimpleBeanDefinitionRegistry
SimpleBeanDefinitionRegistry
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry { /**beanDefinition的容器,通過(guò)ConcurrentHashMap實(shí)現(xiàn). */ private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64); //該類的實(shí)現(xiàn)方法只是實(shí)現(xiàn)了最簡(jiǎn)單的beanDefinition的注入,在Java開(kāi)發(fā)環(huán)境中并不會(huì)使用該實(shí)現(xiàn)類 @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "'beanName' must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); this.beanDefinitionMap.put(beanName, beanDefinition); } }
該實(shí)現(xiàn)類中只做了最簡(jiǎn)單的注入功能,沒(méi)有任何的邏輯處理,因此在實(shí)際開(kāi)發(fā)過(guò)程中Spring并不會(huì)使用該類。
DefaultListableBeanFactory
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { //beanDefinition的容器 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256); //向BeanFactory中注入BeanDefinition public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "Bean name must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); //判斷beanDefinition容器中是否已存在該beanDefinition if (existingDefinition != null) { //是否可以覆蓋 if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } else if (existingDefinition.getRole() < beanDefinition.getRole()) { // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE if (logger.isInfoEnabled()) { logger.info("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else if (!beanDefinition.equals(existingDefinition)) { if (logger.isDebugEnabled()) { logger.debug("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } else { if (logger.isTraceEnabled()) { logger.trace("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + existingDefinition + "] with [" + beanDefinition + "]"); } } //覆蓋beanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); } else { //容器中不存在該beanDefinition的處理 if (hasBeanCreationStarted()) { synchronized (this.beanDefinitionMap) { //對(duì)beanDefinition加鎖 //注入該beanDefinition this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; if (this.manualSingletonNames.contains(beanName)) { Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames); updatedSingletons.remove(beanName); this.manualSingletonNames = updatedSingletons; } } } else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); this.manualSingletonNames.remove(beanName); } this.frozenBeanDefinitionNames = null; } if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } } }
DefaultListableBeanFactory是默認(rèn)使用的注入BeanDefinition的實(shí)現(xiàn)類,可以看到該實(shí)現(xiàn)類中對(duì)注入BeanDefinition做了很多的邏輯判斷,日常開(kāi)發(fā)啟動(dòng)容器過(guò)程中都會(huì)使用該實(shí)現(xiàn)類注入BeanDefinition進(jìn)行后續(xù)的Bean注入。
Bean的注入
BeanDefinition注入后后續(xù)執(zhí)行Bean的注入,bean注入的方式也是將bean注入到bean的容器中,因此在Spring中BeanDefinition和Bean都是通過(guò)容器化的方式操作的,那么在Bean的注入中也通過(guò)對(duì)應(yīng)的接口定義對(duì)Bean的操作,該接口就是SingletonBeanRegistry。
SingletonBeanRegistry接口
該接口實(shí)現(xiàn)了對(duì)Bean的操作:
- SingletonBeanRegistry#registerSingleton(將bean注入到容器中)
- SingletonBeanRegistry#getSingleton(從容器中獲取bean)
public interface SingletonBeanRegistry { //注入bean void registerSingleton(String beanName, Object singletonObject); //獲取bean @Nullable Object getSingleton(String beanName); //是否存在bean boolean containsSingleton(String beanName); String[] getSingletonNames(); int getSingletonCount(); Object getSingletonMutex(); }
SingletonBeanRegistry的實(shí)現(xiàn)類
SingletonBeanRegistry的實(shí)現(xiàn)類有多個(gè),分別為:
- AbstractBeanFactory
- DefaultListableBeanFactory
- DefaultSingletonBeanRegistry
- FactoryBeanRegistrySupport
- AbstractAutowireCapableBeanFactory
下面說(shuō)兩個(gè)有代表性的:AbstractBeanFactory和DefaultSingletonBeanRegistry
AbstractBeanFactory
該實(shí)現(xiàn)類是一個(gè)抽象類,即該類是bean的工廠類,其中主要實(shí)現(xiàn)的是可以復(fù)用的具體邏輯,該抽象類中包含獲取bean、beanPostProcessor、初始化bean、銷毀bean等對(duì)bean的操作抽象類。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { //獲取bean的方式平時(shí)使用ApplicationContext就是最終調(diào)用該方法 public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } @Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } @Override public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false); } public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) throws BeansException { return doGetBean(name, requiredType, args, false); } /** * 從容器中獲取bean的主要邏輯 */ protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //省略部分代碼 try { //先獲取beanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // 單例模式下獲取bean的方式 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) {//原型模式下的bean的獲取 // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); //原型模式每次都需要?jiǎng)?chuàng)建bean prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } //省略部分代碼 return (T) bean; } //將實(shí)現(xiàn)beanPostProcessor的實(shí)現(xiàn)類加入到鏈表中用于對(duì)bean的前置或者后置處理 @Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); // Remove from old position, if any this.beanPostProcessors.remove(beanPostProcessor); // Track whether it is instantiation/destruction aware if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } // Add to end of list this.beanPostProcessors.add(beanPostProcessor); } //銷毀bean的方法 @Override public void destroyBean(String beanName, Object beanInstance) { destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName)); } protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) { new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy(); } }
DefaultSingletonBeanRegistry
該實(shí)現(xiàn)類通過(guò)名字也可以推斷出該實(shí)現(xiàn)類是對(duì)單例bean的注入,該類中實(shí)現(xiàn)了bean的所有容器,平時(shí)開(kāi)發(fā)過(guò)程中Spring容器啟動(dòng)就是使用了該實(shí)現(xiàn)類中的容器,該實(shí)現(xiàn)類是對(duì)bean最終注入的實(shí)現(xiàn),涉及的四個(gè)容器主要有:
- singletonObjects
- singletonFactories
- earlySingletonObjects
- registeredSingletons
四個(gè)容器其中三個(gè)的核心作用是解決循環(huán)依賴,這里不展開(kāi)說(shuō)。
找一條主線梳理下Bean注入的過(guò)程,當(dāng)BeanDefinition注入成功后,后續(xù)執(zhí)行bean的注入,以AbstractAutowireCapableBeanFactory的實(shí)現(xiàn)為例,該實(shí)現(xiàn)類中會(huì)對(duì)bean的注入,整個(gè)注入的鏈路如下:
- 獲取資源數(shù)據(jù):CommonAnnotationBeanPostProcessor#autowireResource
- 通過(guò)beanName解析bean:AbstractAutowireCapableBeanFactory#resolveBeanByName
- 調(diào)用抽象類中獲取bean:AbstractBeanFactory#getBean
- 執(zhí)行抽象類中獲取bean的核心邏輯:AbstractBeanFactory#doGetBean
- bean不存在時(shí)創(chuàng)建bean:AbstractAutowireCapableBeanFactory#createBean
- 獲取單例bean:efaultSingletonBeanRegistry#getSingleton
- 單例bean不存在將類注入到容器中:DefaultSingletonBeanRegistry#addSingleton
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { //單例bean的容器,開(kāi)發(fā)過(guò)程中獲取的bean都是從該容器中獲取的:即所謂的一級(jí)緩存 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //單例bean的beanFactory的容器:即所謂的三級(jí)緩存 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); //提前初始化的bean的容器,該容器的bean并沒(méi)有任何屬性值只是提前將bean注入到該容器中用于后續(xù)的判斷 //即所謂的二級(jí)緩存 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); //已注冊(cè)的單例bean的beanName列表 private final Set<String> registeredSingletons = new LinkedHashSet<>(256); //注入bean的方法 public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, "Bean name must not be null"); Assert.notNull(singletonObject, "Singleton object must not be null"); synchronized (this.singletonObjects) { Object oldObject = this.singletonObjects.get(beanName); if (oldObject != null) { throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"); } addSingleton(beanName, singletonObject); } } /** * 將bean注入容器中,操作四個(gè)容器主要用于bean的循環(huán)依賴問(wèn)題 */ protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
總結(jié)
以上就是對(duì)bean注入從源碼的梳理,該梳理主要從bean注入前的準(zhǔn)備(beanDefinition的注入)和bean注入的實(shí)現(xiàn)來(lái)完成,從整個(gè)梳理中學(xué)到最多的主要有兩點(diǎn):
- 抽象的思想:在BeanDefinition的實(shí)現(xiàn)和Bean的實(shí)現(xiàn)邏輯中,都完成高度抽象并且遵循單一原則和高度抽象,代碼的可擴(kuò)展性和復(fù)用性很高,我們作為開(kāi)發(fā)者也可以通過(guò)Spring暴露的各種Registry接口實(shí)現(xiàn)對(duì)Bean的操作。
- 容器化思想:從BeanDefinition和Bean的注入來(lái)看,整個(gè)的實(shí)現(xiàn)思路都是基于容器化思想來(lái)實(shí)現(xiàn)的,將開(kāi)發(fā)中需要關(guān)心的對(duì)象都實(shí)例化到容器中,開(kāi)發(fā)者在使用時(shí)只要從容器中獲取即可,并且獲取bean的方式也很靈活,開(kāi)發(fā)者在使用和擴(kuò)展性上更便利。
對(duì)于源碼的學(xué)習(xí)自己理解來(lái)說(shuō)并不是背其中的代碼,而是學(xué)習(xí)大佬實(shí)現(xiàn)代碼的思想,為什么可以抽象出擴(kuò)展性這么高的代碼,并且從源頭梳理下來(lái)都能很輕松的按照主線一步一步梳理到目的地,這也是每個(gè)開(kāi)發(fā)者需要學(xué)習(xí)的地方,提高自己代碼的可讀性和可擴(kuò)展性,能夠掌握面向?qū)ο蟮暮诵模?strong>封裝、繼承、多態(tài)。
以上就是Spring中Bean注入源碼示例解析的詳細(xì)內(nèi)容,更多關(guān)于Spring Bean注入的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于SpringBoot和Vue寫(xiě)一個(gè)2048小游戲
創(chuàng)建一個(gè)基于 Java Spring Boot 后端和 Vue 前端的 2048 游戲,可以按照以下步驟進(jìn)行,這個(gè)項(xiàng)目將包括后端(用來(lái)處理游戲邏輯)和前端(用來(lái)顯示游戲界面和與用戶交互),感興趣的小伙伴可以參考本文自己動(dòng)手嘗試一下2024-08-08詳解Spring簡(jiǎn)單容器中的Bean基本加載過(guò)程
本篇將對(duì)定義在 XMl 文件中的 bean,從靜態(tài)的的定義到變成可以使用的對(duì)象的過(guò)程,即 bean 的加載和獲取的過(guò)程進(jìn)行一個(gè)整體的了解2017-05-05MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運(yùn)行 java 代碼
這篇文章主要介紹了MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運(yùn)行 java 代碼,需要的朋友可以參考下2014-10-10Java如何使用流去除集合中某個(gè)字段為空的對(duì)象
這篇文章主要給大家介紹了關(guān)于Java如何使用流去除集合中某個(gè)字段為空的對(duì)象,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-08-08spring中通過(guò)ApplicationContext getBean獲取注入對(duì)象的方法實(shí)例
今天小編就為大家分享一篇關(guān)于spring中通過(guò)ApplicationContext getBean獲取注入對(duì)象的方法實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03java開(kāi)源調(diào)度如何給xxljob加k8s執(zhí)行器
這篇文章主要介紹了java開(kāi)源調(diào)度如何給xxljob加一個(gè)k8s執(zhí)行器,?xxljob?在設(shè)計(jì)上,抽象出了執(zhí)行器的接口,所以實(shí)現(xiàn)一個(gè)語(yǔ)言的執(zhí)行器并不復(fù)雜,這里主要探索下,如何利用k8s的pod?的能力,使用?xxljob?調(diào)度?pod?運(yùn)行,實(shí)現(xiàn)一個(gè)通用的和語(yǔ)言無(wú)關(guān)的執(zhí)行器2022-02-02