zoukankan      html  css  js  c++  java
  • Spring(六)核心容器

    前言

    上篇文章我们对注册 Bean 的核心类 BeanDefinitionRegistry 进行了讨论,这里的注册 Bean 是指保存 Bean 的相关信息,也就是将 Bean 定义成 BeanDefinition,然后放入容器中。除此之外,Spring 还提供一个统一操作单例 Bean 实例的类 SingletonBeanRegistry,通过该类可直接对单例 Bean 的实例进行存储、注册等操作。

    SingletonBeanRegistry

    SingletonBeanRegistry 是一个接口,其定义了操作单例 Bean 实例的一些基础方法:

    public interface SingletonBeanRegistry {
    
    	// 注册单例 Bean。其实就是将该 Bean 保存到一个专门存储单例 Bean 实例的Map中,Key是 beanName,Value是对应的单例 Bean 实例
    	void registerSingleton(String beanName, Object singletonObject);
    
    	// 通过 beanName 获取该单例 Bean 实例
    	Object getSingleton(String beanName);
    
    	// 通过 beanName 判断该单例 Bean 实例是否存在
    	boolean containsSingleton(String beanName);
    
    	// 返回所有单例 Bean 的名称
    	String[] getSingletonNames();
    
    	// 返回已注册的单例 Bean 实例数量
    	int getSingletonCount();
    
    	// 返回当前使用的单例锁,主要提供给外部协作者使用
    	Object getSingletonMutex();
    }
    

    这个接口的核心实现类是 DefaultSingletonBeanRegistry,该类不仅实现了这些基础方法,还针对单例 Bean 扩展了许多功能,如:存储 Bean 之间的依赖关系、存储 Bean 的包含关系(外部类包含内部类)、获取 Bean 所处的状态(正在创建、创建完毕等)、回调销毁 Bean 时触发的 destroy 方法等。

    下面是 DefaultSingletonBeanRegistry 类中的核心属性和方法:

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    
        /********** 1、定义的一些 Map 属性,用来保存单例 Bean 实例、 Bean 的依赖关系 **********/
    
    	// 缓存单例 Bean 实例,Key 是 beanName,Value 是单例 Bean 实例
    	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    	// 缓存 Bean 对应的 ObjectFactory 
    	//      ObjectFactory 是获取 Bean 实例的工厂,只不过这里获取的 Bean 还未完全实例化,属于提早暴露的 Bean
    	//      该属性在解决循环依赖时使用,后续会深入讨论
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    	// 缓存 singletonFactories 属性中通过 ObjectFactory 创建的 Bean
    	//      该属性也是在解决循环依赖时使用,后续会深入讨论
    	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
    	// 保存已注册的单例 Bean 名称
    	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
    
    	// 保存当前正在创建的 Bean 的名称
    	private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
    	// 保存当前从创建检查中排除的 Bean 的名称
    	private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
    	...
    	
    	// 当前 Bean 是否处于销毁状态
    	private boolean singletonsCurrentlyInDestruction = false;
    
    	// 保存实现了 DisposableBean 接口的 Bean,在销毁 Bean 时,会回调该 Bean 中的 destory 方法
    	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
    
    	// 保存 Bean 的包含关系,key 是 Bean 的名称,value 是 Bean 里面包含的其它 Bean 名称集合
    	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
    
    	// 保存 Bean 的依赖关系:key 是 Bean 的名称,value 是依赖于该 Bean 的其它 Bean 名称集合
    	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
    
    	// 保存 Bean 的依赖关系:key 是 Bean 的名称,value 是该 Bean 所依赖的其它 Bean 名称集合
    	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
    
        /******************************** 2、注册单例 Bean 实例及对应的实例工厂 ********************************/
    
        // 注册单例 Bean 实例
    	@Override
    	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) {
    		    // 通过 beanName 获取 Map 中对应的单例 Bean 实例
    			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 方法
    			addSingleton(beanName, singletonObject);
    		}
    	}
    
        // 缓存单例 Bean 实例
    	protected void addSingleton(String beanName, Object singletonObject) {
    		synchronized (this.singletonObjects) {
    			// 将单例 Bean 实例存放至 singletonObjects 集合
    			this.singletonObjects.put(beanName, singletonObject);
    			
    			// 当 beanName 对应的 Bean 实例已被存放至 singletonObjects 集合时,singletonFactories 
    			// 和 earlySingletonObjects 集合则不能再持有 beanName 对应的 ObjectFactory 和实例
    			// 其中原因会在后续循环依赖的文章深入讨论
    			this.singletonFactories.remove(beanName);
    			this.earlySingletonObjects.remove(beanName);
    			
    			// 存储 Bean 名称
    			this.registeredSingletons.add(beanName);
    		}
    	}
    
    	// 缓存 Bean 对应的 ObjectFactory
    	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    		Assert.notNull(singletonFactory, "Singleton factory must not be null");
    		synchronized (this.singletonObjects) {
    			if (!this.singletonObjects.containsKey(beanName)) {
    				this.singletonFactories.put(beanName, singletonFactory);
    				this.earlySingletonObjects.remove(beanName);
    				this.registeredSingletons.add(beanName);
    			}
    		}
    	}
    
        /********************************* 3、获取单例 Bean 实例 *********************************/
        
    	@Override
    	public Object getSingleton(String beanName) {
    		
    		// 该方法较为复杂,在后续结合循环依赖的场景讨论
    		
    	}
    
    	...
    
    	/***************************** 4、对单例 Bean 实例的基础操作 *****************************/
    
    	// 删除单例 Bean 实例
    	protected void removeSingleton(String beanName) {
    		synchronized (this.singletonObjects) {
    			this.singletonObjects.remove(beanName);
    			this.singletonFactories.remove(beanName);
    			this.earlySingletonObjects.remove(beanName);
    			this.registeredSingletons.remove(beanName);
    		}
    	}
    
        // 判断 beanName 对应的单例 Bean 实例时候存在
    	@Override
    	public boolean containsSingleton(String beanName) {
    		return this.singletonObjects.containsKey(beanName);
    	}
    
        // 返回所有单例 Bean 的 beanName
    	@Override
    	public String[] getSingletonNames() {
    		synchronized (this.singletonObjects) {
    			return StringUtils.toStringArray(this.registeredSingletons);
    		}
    	}
    
        // 返回单例 Bean 实例数量
    	@Override
    	public int getSingletonCount() {
    		synchronized (this.singletonObjects) {
    			return this.registeredSingletons.size();
    		}
    	}
    
    	...
    
    	/*************************************** 5、 Bean 的状态 **************************************/
    
        // beanName 对应的 Bean 是否处于实例化阶段
    	public boolean isCurrentlyInCreation(String beanName) {
    		Assert.notNull(beanName, "Bean name must not be null");
    		return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
    	}
    	protected boolean isActuallyInCreation(String beanName) {
    		return isSingletonCurrentlyInCreation(beanName);
    	}
    	public boolean isSingletonCurrentlyInCreation(String beanName) {
    		return this.singletonsCurrentlyInCreation.contains(beanName);
    	}
    
    	// 单例 Bean 实例化前执行,将正要创建的 Bean 加入 singletonsCurrentlyInCreation 集合
    	protected void beforeSingletonCreation(String beanName) {
    		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);
    		}
    	}
    
    	// 单例 Bean 实例化后执行,从 singletonsCurrentlyInCreation 集合中移除已创建的 Bean 
    	protected void afterSingletonCreation(String beanName) {
    		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
    			throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    		}
    	}
    
    	...
    
    	/********************* 6、 存储 Bean 之间的关系、判断 Bean 之间的关系 *********************/
    	
    	// 保存具有包含关系的 Bean(内部类与外部类)
    	public void registerContainedBean(String containedBeanName, String containingBeanName) {
    		synchronized (this.containedBeanMap) {
    			Set<String> containedBeans =
    					this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
    			if (!containedBeans.add(containedBeanName)) {
    				return;
    			}
    		}
    		registerDependentBean(containedBeanName, containingBeanName);
    	}
    
    	// 保存具有依赖关系的 Bean
    	public void registerDependentBean(String beanName, String dependentBeanName) {
    		String canonicalName = canonicalName(beanName);
    
    		synchronized (this.dependentBeanMap) {
    			Set<String> dependentBeans =
    					this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
    			if (!dependentBeans.add(dependentBeanName)) {
    				return;
    			}
    		}
    
    		synchronized (this.dependenciesForBeanMap) {
    			Set<String> dependenciesForBean =
    					this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
    			dependenciesForBean.add(canonicalName);
    		}
    	}
    
    	...
    	
    	/***************************** 7、 销毁 Bean 的方法 *****************************/
    	
        ...
    }
    

    DefaultSingletonBeanRegistry 类中的属性及方法虽然很多,但也有规律可循的,大致分为对单例 Bean 实例的操作、管理 Bean 之间关系、针对 Bean 的不同状态进行操作及销毁 Bean 的操作。

    该类中的核心还是那些 Map,类中的所有方法都是对这些 Map 进行操作,而这些 Map 中存储的是不同场景下的单例 Bean 。

    最后

    关于 SingletonBeanRegistry 就介绍到这,其主要还是针对单例 Bean 进行操作,外部调用者统一继承该类操作单例 Bean,其主要调用者还是 DefaultListableBeanFactory,前篇文章也说过,这是我们当前上下文环境中使用的 BeanFactory 工厂类,在工厂类中执行 getBean 操作时,会调用这些方法,后续会详细讨论 getBean 操作。最后值得注意是,Spring 也是在该类中解决循环依赖问题,这部分也会在后面详细讨论。

  • 相关阅读:
    Charles抓包使用教程
    学习规划
    log重复数据
    CNN实现推特文本分类
    conda env
    matplotlib画基础表
    决策树算法
    sklearn实现决策树
    分词与文本预处理工具
    matplotlib作图学习(1)
  • 原文地址:https://www.cnblogs.com/loongk/p/12302360.html
Copyright © 2011-2022 走看看