• Sping源码(九)—— Bean的初始化(非懒加载)— doGetBean


    序言

    我们前两篇文章介绍了Bean初始化的准备工作,这篇文章正式介绍Bean的加载过程,看看getBean()中都做了什么。
    在这里插入图片描述

    getBean()

    其实在之前有提到过,bean的加载并不是都在finishBeanFactoryInitialization方法中进行,而更早的在BFPP和BDRPP中就有看到显式的getBean方法的调用,所以我们这次换个入口,从invokeBeanFactoryPostProcessors中看getBean()

    invokeBeanFactoryPostProcessors
    可以看到在invokeBeanFactoryPostProcessors方法中对getBean()的显式调用。

    	//省略部分源码
    	public static void invokeBeanFactoryPostProcessors(
    			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
    		if (beanFactory instanceof BeanDefinitionRegistry) {
    			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    
    			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    			String[] postProcessorNames =
    					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    			for (String ppName : postProcessorNames) {
    				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    				}
    			}
    		}
         }
    

    doGetBean
    流程图
    在这里插入图片描述

    getBean()方法中直接对doGetBean()方法进行调用。

    public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    		return doGetBean(name, requiredType, null, false);
    	}
    
    protected <T> T doGetBean(
    			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
    			throws BeansException {
    		//获取最终的beanName
    		String beanName = transformedBeanName(name);
    		Object bean;
    
    		// Eagerly check singleton cache for manually registered singletons.
    		// 主动检查手工注册的单例缓存。(尝试从singletonObject缓存中获取,解决循环依赖)
    		Object sharedInstance = getSingleton(beanName);
    		//如果单例缓存中不为null,则看该实例是否实现了FactoryBean,如果实现了则创建实例
    		if (sharedInstance != null && args == null) {
    			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    		}
    
    		else {
    			// Fail if we're already creating this bean instance:
    			// We're assumably within a circular reference.
    
    			// 判断scope = prototype的实例bean是否在创建中
    			if (isPrototypeCurrentlyInCreation(beanName)) {
    				throw new BeanCurrentlyInCreationException(beanName);
    			}
    
    			// Check if bean definition exists in this factory.
    			//获取父类的beanFactory
    			//Spring中都是单一容器,SpringMVC中会存在父子容器
    			BeanFactory parentBeanFactory = getParentBeanFactory();
    			//如果父工厂不为null,并且当前BeanFactory中不包含该bean
    			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    				// Not found -> check parent.
    				// 获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
    				String nameToLookup = originalBeanName(name);
    				//如果父工厂是AbstractBeanFactory,则调用父工厂doGetBean方法进行实例的创建
    				if (parentBeanFactory instanceof AbstractBeanFactory) {
    					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
    							nameToLookup, requiredType, args, typeCheckOnly);
    				}
    				else if (args != null) {
    					// Delegation to parent with explicit args.
    					// 如果有创建bean实例时要使用的参数
    					//使用父工厂获取该bean对象, bean全类名和创建bean实例时要使用的参数
    					return (T) parentBeanFactory.getBean(nameToLookup, args);
    				}
    				else if (requiredType != null) {
    					// No args -> delegate to standard getBean method.
    					// 没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。
    					// 使用父工厂获取该bean对象,通bean全类名和所需的bean类型
    					return parentBeanFactory.getBean(nameToLookup, requiredType);
    				}
    				else {
    					// 使用父工厂获取bean,通过bean全类名
    					return (T) parentBeanFactory.getBean(nameToLookup);
    				}
    			}
    			//根据传递的typeCheckOnly来进行判断,这里是false
    			if (!typeCheckOnly) {
    				//放入alreadyCreated缓存中,标记当前bean已经创建,
    				markBeanAsCreated(beanName);
    			}
    			try {
    				//将bean进行merge操作,返回merge后的RootBeanDefinition
    				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    				//如果当前bean是Abstract,抛出异常
    				checkMergedBeanDefinition(mbd, beanName, args);
    
    				// Guarantee initialization of beans that the current bean depends on.
    				// 如果存在依赖的bean的话,那么则优先实例化依赖的bean
    				String[] dependsOn = mbd.getDependsOn();
    				if (dependsOn != null) {
    					// 如果存在依赖,则需要递归实例化依赖的bean
    					for (String dep : dependsOn) {
    						// 如果beanName已注册依赖于dependentBeanName的关系
    						if (isDependent(beanName, dep)) {
    							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
    						}
    						// 注册各个bean的依赖关系,方便进行销毁
    						registerDependentBean(dep, beanName);
    						try {
    							// 递归优先实例化被依赖的Bean
    							getBean(dep);
    						}
    					}
    				}
    
    				// Create bean instance.
    				//bean的范围是 SINGLETON 或者 DEFAULT
    				//创建bean的实例对象
    				if (mbd.isSingleton()) {
    					//从缓存中获取实例bean
    					sharedInstance = getSingleton(beanName, () -> {
    						try {
    							//创建bean
    							return createBean(beanName, mbd, args);
    						}
    						catch (BeansException ex) {
    							
    							destroySingleton(beanName);
    							throw ex;
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    				}
    				// 如果 bean的范围是 PROTOTYPE
    				else if (mbd.isPrototype()) {
    					// It's a prototype -> create a new instance.
    					//如果是 PROTOTYPE,则创建一个新实例
    					Object prototypeInstance = null;
    					try {
    						//创建bean实例钱的准备工作,将beanName添加到ThreadLocal中,表示当前bean正在创建中
    						beforePrototypeCreation(beanName);
    						//创建实例
    						prototypeInstance = createBean(beanName, mbd, args);
    					}
    					finally {
    						//创建完实例后,将beanName从ThreadLocal中移除
    						afterPrototypeCreation(beanName);
    					}
    					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    				}
    
    				else {
    					String scopeName = mbd.getScope();
    					//如果scopeName 为 null 则抛出异常。
    					if (!StringUtils.hasLength(scopeName)) {
    						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
    					}
    					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, () -> {
    							//使用 ThreadLocal 作为缓存
    							beforePrototypeCreation(beanName);
    							try {
    								return createBean(beanName, mbd, args);
    							}
    							finally {
    								//创建完实例后,将beanName从ThreadLocal中移除
    								afterPrototypeCreation(beanName);
    							}
    						});
    						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    					}
    				}
    			}
    		}
    		return (T) bean;
    	}
    

    getSingleton
    首先尝试从一级缓存singletonObjects中获取对象。

      /**
         * 获取单例对象。
         * 此方法用于在单例对象创建过程中或者创建后获取该对象。
    	 * 如果对象还未完全创建,根据allowEarlyReference参数决定是否返回一个早期引用。
         *
         * @param beanName 要获取的Bean的名称。
         * @param allowEarlyReference 如果为true,并且bean允许早期引用,那么在单例对象还没有完全创建时也可以返回这个对象的早期引用。
         * @return 返回指定beanName的单例对象。如果没有找到对应的单例对象,且不允许早期引用,或者不允许早期访问,则返回null。
         */
    	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    		// 快速检查是否已有实例,无需完全锁定单例
    		Object singletonObject = this.singletonObjects.get(beanName);
    		// 如果singletonObject缓存中没有找到,&&
    		// singletonsCurrentlyInCreation中有(说明该bean正在创建中)
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			//从早期单例对象缓存中获取,(之所称成为早期单例对象,是因为earlySingletonObjects里
    			// 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
    			singletonObject = this.earlySingletonObjects.get(beanName);
    			// 如果早期单例对象缓存也没有,并且允许创建早期单例对象引用
    			if (singletonObject == null && allowEarlyReference) {
    				synchronized (this.singletonObjects) {
    					singletonObject = this.singletonObjects.get(beanName);
    					if (singletonObject == null) {
    						singletonObject = this.earlySingletonObjects.get(beanName);
    						if (singletonObject == null) {
    							// 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactories
    							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    							if (singletonFactory != null) {
    								// 如果存在单例工厂对象,则调用其getObject方法获取单例对象
    								singletonObject = singletonFactory.getObject();
    								// 存储获取到的singletonObject为早期引用,并移除对应的singletonFactory
    								this.earlySingletonObjects.put(beanName, singletonObject);
    								// 从三级缓存中移除
    								this.singletonFactories.remove(beanName);
    							}
    						}
    					}
    				}
    			}
    		}
    		//返回singletonObject
    		return singletonObject;
    	}
    

    扩展一:标志位 当前Bean是否正在进行创建作用

    上面源码中可以看到对当前Bean创建状态的判断。

    	protected void beforeSingletonCreation(String beanName) {
    		// 如果当前在创建检查中的排除bean名列表中不包含该beanName且将beanName添加到当前正在创建的bean名称列表后,出现
    		// beanName已经在当前正在创建的bean名称列表中添加过
    		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);
    		}
    	}
    

    作用在于:如果以时间维度来看,一个Bean的创建过程大致可以分为 新生状态 -》 开始创建 -》 … -》 完整对象。
    如果我当前Bean尚未创建完成,此时想要直接获取实例对象,是不可以的,所以状态标志位可以用来判断当前Bean的创建状态。
    在这里插入图片描述

    扩展二:ObjectFactory

    源码中的这里有一个lamda表达式,并return了createBean(),那createBean()方法是在什么时候进行调用的呢? 是作为getSingleton方法的参数,在getSingleton之前么?

    	if (mbd.isSingleton()) {
    		//从缓存中获取实例bean
    		sharedInstance = getSingleton(beanName, () -> {
    			try {
    				//创建bean
    				return createBean(beanName, mbd, args);
    			}
    			catch (BeansException ex) {
    				destroySingleton(beanName);
    				throw ex;
    			}
    		});
    		bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    	}
    

    可以看到getSingleton方法中有个参数为ObjectFactory singletonFactory类型,而createBean方法的调用会在下面源码中执行singletonFactory.getObject();方法时,进行调用。

    	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    		synchronized (this.singletonObjects) {
    			// 快速检查是否已有实例
    			Object singletonObject = this.singletonObjects.get(beanName);
    			//如果缓存中没有
    			if (singletonObject == null) {
    				//标志位,标志当前bean是否正在销毁
    				if (this.singletonsCurrentlyInDestruction) {
    					throw new BeanCreationNotAllowedException;
    				}
    				// 创建单例之前的回调,默认实现将单例注册为当前正在创建中
    				beforeSingletonCreation(beanName);
    				//生成新的单例对象的标记, 当前为false 表示尚未生成新的单例对象
    				boolean newSingleton = false;
    				//suppressedExceptions标记 = null , 则实例化 suppressedExceptions
    				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
    				if (recordSuppressedExceptions) {
    					this.suppressedExceptions = new LinkedHashSet<>();
    				}
    				try {
    					// 会调用 singletonFactory 中的方法创建单例对象,这里是 createBean() 方法
    					singletonObject = singletonFactory.getObject();
    					//生成新的单例对象后,改变标记为 true
    					newSingleton = true;
    				}
    				finally {
    					if (recordSuppressedExceptions) {
    						this.suppressedExceptions = null;
    					}
    					afterSingletonCreation(beanName);
    				}
    				if (newSingleton) {
    					addSingleton(beanName, singletonObject);
    				}
    			}
    			return singletonObject;
    		}
    	}
    

    ObjectFactory
    源码中包含着@FunctionalInterface注解,说明是一个函数式编程,而函数式编程的调用,会在调用getObject()时,执行createBean方法。

    @FunctionalInterface
    public interface ObjectFactory<T> {
    	T getObject() throws BeansException;
    }
    
  • 相关阅读:
    疫苗预约系统毕业设计,疫苗预约系统设计源码,疫苗预约系统开题报告需求分析
    【Python基础】高级数据类型:初识 “列表” || 列表的增删改查 || del关键字 || 列表的定义
    IP组成,分类,子网划分
    技术人应该广度还是深度学习?
    Python3出现的Error总结
    小白兔快开门,我是你爸爸。WEB安全基础入门—访问控制漏洞和权限提升
    什么是Docker容器?Docker容器和VM有什么区别?
    亚马逊鲲鹏系统优势有哪些
    基于SSH开发网上机票销售系统
    树莓派也能用于心脏病数据安全管理!
  • 原文地址:https://blog.csdn.net/weixin_43936962/article/details/139353432