亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring中Bean注入源碼示例解析

 更新時間:2023年01月15日 16:57:16   作者:陳湯姆  
這篇文章主要為大家介紹了Spring中Bean注入源碼示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

BeanDefinition和Bean

在Spring中Bean的注入涉及兩部分:

  • BeanDefinition
  • Bean

兩個對象存在先后順序,先注入BeanDefinition之后才執(zhí)行Bean對象的注入。

那么兩者有什么關(guān)聯(lián)呢?

BeanDefinition和Bean的關(guān)系:可以理解為BeanDefinition是Bean的包裝類,類似Java中類和屬性的關(guān)系。

BeanDefinition是對Bean對象的包裝,BeanDefinition中封裝了Bean相關(guān)的描述,比如bean對象,bean的單例還是原型、bean的父級、懶加載方式等等。

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ù),該類中實例化了Bean對象為Object。因此在BeanDefinition中調(diào)用getSource就可以獲取到Bean對象。

分清楚BeanDefinition和Bean之后再看BeanDefinition的注入,因為只有注入了BeanDefinition才會注入后續(xù)的Bean。

BeanDefinition的注入

BeanDefinitionRegistry接口

BeanDefinitin的注入通過接口BeanDefinitionRegistry抽象了各種對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ǔ)接口,該類是一個接口類型并不是一個抽象類,因此該接口中不會定義任何BeanDefinition的容器,BeanDefinition的容器只在各實現(xiàn)類中定義并使用。任何需要操作BeanDefinition的實現(xiàn)都需要實現(xiàn)該接口。

BeanDefinitionRegistry的實現(xiàn)類

找到操作BeanDefinition的接口就可以通過接口查看接口的實現(xiàn)類,進而找到BeanDefinition的應用。

BeanDefinition常見的幾個實現(xiàn)類有:

  • DefaultListableBeanFactory
  • SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistry

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {
	/**beanDefinition的容器,通過ConcurrentHashMap實現(xiàn). */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);
	//該類的實現(xiàn)方法只是實現(xiàn)了最簡單的beanDefinition的注入,在Java開發(fā)環(huán)境中并不會使用該實現(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);
	}
}

該實現(xiàn)類中只做了最簡單的注入功能,沒有任何的邏輯處理,因此在實際開發(fā)過程中Spring并不會使用該類。

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) { //對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是默認使用的注入BeanDefinition的實現(xiàn)類,可以看到該實現(xiàn)類中對注入BeanDefinition做了很多的邏輯判斷,日常開發(fā)啟動容器過程中都會使用該實現(xiàn)類注入BeanDefinition進行后續(xù)的Bean注入。

Bean的注入

BeanDefinition注入后后續(xù)執(zhí)行Bean的注入,bean注入的方式也是將bean注入到bean的容器中,因此在Spring中BeanDefinition和Bean都是通過容器化的方式操作的,那么在Bean的注入中也通過對應的接口定義對Bean的操作,該接口就是SingletonBeanRegistry。

SingletonBeanRegistry接口

該接口實現(xiàn)了對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的實現(xiàn)類

SingletonBeanRegistry的實現(xiàn)類有多個,分別為:

  • AbstractBeanFactory
  • DefaultListableBeanFactory
  • DefaultSingletonBeanRegistry
  • FactoryBeanRegistrySupport
  • AbstractAutowireCapableBeanFactory

下面說兩個有代表性的:AbstractBeanFactory和DefaultSingletonBeanRegistry

AbstractBeanFactory

該實現(xiàn)類是一個抽象類,即該類是bean的工廠類,其中主要實現(xiàn)的是可以復用的具體邏輯,該抽象類中包含獲取bean、beanPostProcessor、初始化bean、銷毀bean等對bean的操作抽象類。

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	//獲取bean的方式平時使用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);
						//原型模式每次都需要創(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;
	}
	//將實現(xiàn)beanPostProcessor的實現(xiàn)類加入到鏈表中用于對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

該實現(xiàn)類通過名字也可以推斷出該實現(xiàn)類是對單例bean的注入,該類中實現(xiàn)了bean的所有容器,平時開發(fā)過程中Spring容器啟動就是使用了該實現(xiàn)類中的容器,該實現(xiàn)類是對bean最終注入的實現(xiàn),涉及的四個容器主要有:

  • singletonObjects
  • singletonFactories
  • earlySingletonObjects
  • registeredSingletons

四個容器其中三個的核心作用是解決循環(huán)依賴,這里不展開說。

找一條主線梳理下Bean注入的過程,當BeanDefinition注入成功后,后續(xù)執(zhí)行bean的注入,以AbstractAutowireCapableBeanFactory的實現(xiàn)為例,該實現(xiàn)類中會對bean的注入,整個注入的鏈路如下:

  • 獲取資源數(shù)據(jù):CommonAnnotationBeanPostProcessor#autowireResource
  • 通過beanName解析bean:AbstractAutowireCapableBeanFactory#resolveBeanByName
  • 調(diào)用抽象類中獲取bean:AbstractBeanFactory#getBean
  • 執(zhí)行抽象類中獲取bean的核心邏輯:AbstractBeanFactory#doGetBean
  • bean不存在時創(chuàng)建bean:AbstractAutowireCapableBeanFactory#createBean
  • 獲取單例bean:efaultSingletonBeanRegistry#getSingleton
  • 單例bean不存在將類注入到容器中:DefaultSingletonBeanRegistry#addSingleton
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	//單例bean的容器,開發(fā)過程中獲取的bean都是從該容器中獲取的:即所謂的一級緩存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
	//單例bean的beanFactory的容器:即所謂的三級緩存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
	//提前初始化的bean的容器,該容器的bean并沒有任何屬性值只是提前將bean注入到該容器中用于后續(xù)的判斷
	//即所謂的二級緩存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
	//已注冊的單例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注入容器中,操作四個容器主要用于bean的循環(huá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é)

以上就是對bean注入從源碼的梳理,該梳理主要從bean注入前的準備(beanDefinition的注入)和bean注入的實現(xiàn)來完成,從整個梳理中學到最多的主要有兩點:

  • 抽象的思想:在BeanDefinition的實現(xiàn)和Bean的實現(xiàn)邏輯中,都完成高度抽象并且遵循單一原則和高度抽象,代碼的可擴展性和復用性很高,我們作為開發(fā)者也可以通過Spring暴露的各種Registry接口實現(xiàn)對Bean的操作。
  • 容器化思想:從BeanDefinition和Bean的注入來看,整個的實現(xiàn)思路都是基于容器化思想來實現(xiàn)的,將開發(fā)中需要關(guān)心的對象都實例化到容器中,開發(fā)者在使用時只要從容器中獲取即可,并且獲取bean的方式也很靈活,開發(fā)者在使用和擴展性上更便利。

對于源碼的學習自己理解來說并不是背其中的代碼,而是學習大佬實現(xiàn)代碼的思想,為什么可以抽象出擴展性這么高的代碼,并且從源頭梳理下來都能很輕松的按照主線一步一步梳理到目的地,這也是每個開發(fā)者需要學習的地方,提高自己代碼的可讀性和可擴展性,能夠掌握面向?qū)ο蟮暮诵模?strong>封裝、繼承、多態(tài)。

以上就是Spring中Bean注入源碼示例解析的詳細內(nèi)容,更多關(guān)于Spring Bean注入的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 基于SpringBoot和Vue寫一個2048小游戲

    基于SpringBoot和Vue寫一個2048小游戲

    創(chuàng)建一個基于 Java Spring Boot 后端和 Vue 前端的 2048 游戲,可以按照以下步驟進行,這個項目將包括后端(用來處理游戲邏輯)和前端(用來顯示游戲界面和與用戶交互),感興趣的小伙伴可以參考本文自己動手嘗試一下
    2024-08-08
  • 詳解Spring簡單容器中的Bean基本加載過程

    詳解Spring簡單容器中的Bean基本加載過程

    本篇將對定義在 XMl 文件中的 bean,從靜態(tài)的的定義到變成可以使用的對象的過程,即 bean 的加載和獲取的過程進行一個整體的了解
    2017-05-05
  • MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運行 java 代碼

    MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運行 java 代碼

    這篇文章主要介紹了MAC 系統(tǒng)如何使用 Sublime Text 2 直接編譯運行 java 代碼,需要的朋友可以參考下
    2014-10-10
  • java hashtable實現(xiàn)代碼

    java hashtable實現(xiàn)代碼

    這篇文章介紹了java hashtable實現(xiàn)代碼,有需要的朋友可以參考一下
    2013-10-10
  • Java鎖之阻塞鎖介紹和代碼實例

    Java鎖之阻塞鎖介紹和代碼實例

    這篇文章主要介紹了Java鎖之阻塞鎖介紹和代碼實例,阻塞鎖與自旋鎖不同,它改變了線程的運行狀態(tài),需要的朋友可以參考下
    2014-09-09
  • Java如何使用流去除集合中某個字段為空的對象

    Java如何使用流去除集合中某個字段為空的對象

    這篇文章主要給大家介紹了關(guān)于Java如何使用流去除集合中某個字段為空的對象,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Java具有一定的參考學習價值,需要的朋友可以參考下
    2023-08-08
  • Fluent Mybatis讓你擺脫Xml文件的技巧

    Fluent Mybatis讓你擺脫Xml文件的技巧

    Fluent-Mybatis類似于Mybatis-Plus是對Mybatis進一步的封裝,可以只用一個實體類對象,通過代碼生成器,在編譯的過程中生成所需要的各類文件,簡化了項目的基礎(chǔ)構(gòu)建,提高開發(fā)效率,本文重點給大家介紹Fluent Mybaits讓你擺脫Xml文件的技巧,一起看看吧
    2021-08-08
  • spring中通過ApplicationContext getBean獲取注入對象的方法實例

    spring中通過ApplicationContext getBean獲取注入對象的方法實例

    今天小編就為大家分享一篇關(guān)于spring中通過ApplicationContext getBean獲取注入對象的方法實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • java開源調(diào)度如何給xxljob加k8s執(zhí)行器

    java開源調(diào)度如何給xxljob加k8s執(zhí)行器

    這篇文章主要介紹了java開源調(diào)度如何給xxljob加一個k8s執(zhí)行器,?xxljob?在設(shè)計上,抽象出了執(zhí)行器的接口,所以實現(xiàn)一個語言的執(zhí)行器并不復雜,這里主要探索下,如何利用k8s的pod?的能力,使用?xxljob?調(diào)度?pod?運行,實現(xiàn)一個通用的和語言無關(guān)的執(zhí)行器
    2022-02-02
  • Spring創(chuàng)建Bean的6種方式詳解

    Spring創(chuàng)建Bean的6種方式詳解

    這篇文章主要介紹了Spring創(chuàng)建Bean的6種方式詳解,本文講解了在Spring 應用中創(chuàng)建Bean的多種方式,包括自動創(chuàng)建,以及手動創(chuàng)建注入方式,實際開發(fā)中可以根據(jù)業(yè)務場景選擇合適的方案。,需要的朋友可以參考下
    2019-06-06

最新評論