Spring源碼解析之【BeanFactory】與【BeanDefinitionRegistry】

Spring的一個非常重要的概念的就是Bean,Spring容器需要通過掃描和註冊來實現對Bean信息的管理。在分析了Spring的源碼之後發現,Spring裏面用了很多的BeanFactory,這個類非常重要,因爲實際上在Spring中BeanFactoryIOC容器的實際代表者,它用來創建和管理Bean。它爲其他具體的IOC容器提供了最基本的規範,它是一個接口類型。

BeanFactory是最典型的工廠方法模式。不同類型的工廠會生產不同類型的商品。它的子接口和對應的實現類結構如下:

1. BeanFactory接口

在這裏插入圖片描述

我們可以看到在BeanFactory接口下面有三個子接口:

  • HierarchicalBeanFactory:提供父容器的訪問功能
    • ConfigurableBeanFactory 接口
  • AutowireCapableBeanFactory:在BeanFactory基礎上是實現了對已存在實例的管理
  • ListableBeanFactory:提供了批量獲取Bean的方法

接口ConfigurableListableBeanFactory繼承了上述的三個接口,增加了一些其他的功能:如類加載器、類型轉換,屬性編輯器,BeanPostProcessorBean定義等

實現類DefaultListableBeanFactory繼承ConfigurableListableBeanFactory接口,實現了所有的BeanFactory功能,且可以註冊BeanDefinition

1.1 ListableBeanFactory接口

上面的第一個圖片沒有截全,遺漏了ListableBeanFactory的部分實現類信息,且這個實現類還比較重要,因此再增加一個圖片。

在這裏插入圖片描述
我們可以看到AnnotataionConfigApplicationContext實現了ListableBeanFactory接口。AnnotataionConfigApplicationContext類是註解驅動去掃描Bean的定義信息。這個類我們很熟悉,因爲在Spring啓動的時候就是利用這個類:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig_AOP.class);

在使用BeanFactory工廠創建Bean的過程中,我們需要利用BeanDefinitionRegistry將這些Bean註冊到DefaultListableBeanFactory中。那麼接下來就介紹一下BeanDefinitionRegistry

2. BeanDefinitionRegistry接口

public interface BeanDefinitionRegistry extends AliasRegistry 

從上述代碼可以看出,BeanDefinitionRegistry接口實現了AliasRegistry接口,它主要的工作就是定義Bean的常規操作。

它有三個子接口:

  • SimpleBeanDefinitionRegistry實現類
  • DefaultListableBeanFactory實現類
    • 基本實現類 ,擁有registryBeanDefinition功能
  • GenericApplicationContext實現類
    在這裏插入圖片描述

2.1 BeanDefinitionRegistry接口的功能

public interface BeanDefinitionRegistry extends AliasRegistry {

	// 向beanFactory中註冊一個BeanDefinition
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	// 根據beanName從beanFactory中移除一個已經註冊的BeanDefinition
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	// 根據beanName從beanFactory中獲取一個BeanDefinition
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	// 判斷beanFactory中是否有beanName的BeanDefinition
	boolean containsBeanDefinition(String beanName);

	// 獲取beanFactory中的所有BeanDefinition的beanName
	String[] getBeanDefinitionNames();

	// 獲取beanFactory中的BeanDefinition的數量
	int getBeanDefinitionCount();

	// 判斷beanFactory中的beanName是否被佔用
	boolean isBeanNameInUse(String beanName);

}

2.2 SimpleBeanDefinitionRegistry

BeanDefinitionRegistry的一個簡單實現方式,沒有內置的beanFactory,這個類是用來留給我們測試用的。開發情況下Spring不會使用該類。
這個類的功能很簡單,這裏就不做詳細介紹了,根據方法的名稱就可以看出對應的方法所實現的功能。

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {

	// 使用ConcurrentHashMap來存儲beanName和BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);


	@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);
	}

	@Override
	public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		if (this.beanDefinitionMap.remove(beanName) == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
	}

	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
	}

	@Override
	public boolean containsBeanDefinition(String beanName) {
		return this.beanDefinitionMap.containsKey(beanName);
	}

	@Override
	public String[] getBeanDefinitionNames() {
		return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
	}

	@Override
	public int getBeanDefinitionCount() {
		return this.beanDefinitionMap.size();
	}

	@Override
	public boolean isBeanNameInUse(String beanName) {
		return isAlias(beanName) || containsBeanDefinition(beanName);
	}

}

2.3 DefaultListableBeanFactory

這個類非常重要,它是BeanDefinitionResgitry接口的基本實現,實際上很多beanFactory最後都是調用DefaultListableBeanFactory類的registryBeanFactory來註冊beanDefinition.

這個類裏面有非常多的方法,這裏只介紹比較重要的registryBeanFactory方法的實現

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

	// 以Map的數據結構保存beanName和BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
	// 保存所有beanDefinition的名字
	private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);

	// 註冊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 oldBeanDefinition;
		// 先判斷當前的beanName對應的bean信息是否已經存在
		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
			// 是否允許覆蓋
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
						"': There is already [" + oldBeanDefinition + "] bound.");
			}
			// 若允許覆蓋  那還得比較下role  如果新進來的這個Bean的role更大	
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (this.logger.isWarnEnabled()) {
					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(oldBeanDefinition)) {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// hasBeanCreationStarted:說明已經存在bean已經在創建了
				synchronized (this.beanDefinitionMap) {
					// 將beanName和beanDefinition放進去
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// 仍然處在Spring啓動階段
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

2.4AnnotationConfigApplicationContext

這個類是GenericApplicationContext的子類,但是通過分析這個類的方法,發現並沒有registryBeanDefinition方法。

在這裏插入圖片描述

雖然沒有registryBeanDefinition方法,但是又register方法,而register方法又調用了AnnotatedBeanDefinitionReader類的register方法,經過一系列的操作,最後調用了DefaultListableBeanFactory類的registerBeanDefinition 方法

3 總結

  1. Spring使用BeanFactory作爲創建Bean的工廠,利用BeanDefinitionRegistry來註冊BeanDefinition,實際上都是使用DefaultListableBeanFactory類的registerBeanDefinition

參考並感謝

  1. https://blog.csdn.net/f641385712/article/details/89518940
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章