• 【Sping 源码解析】Spring XML方式准备创建bean


    1、前言

    上文Spring XML方式获取bean源码初步解析讲述了spring 创建bean的概览后对源码初步的解析。

    主要涉及的是:

    2.1、获取真正的beanName
    2.2、从缓存中获取bean
    2.3、获取bean实例
    2.4、检测是否是抽象
    2.5、处理依赖的bean
    2.6、判断是否是单例
    2.7、判断是否是原型
    2.8、非单例和原型的作用域统一处理
    2.9、对获取bean的类型和需要的类型进行校验
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    其中对于除创建bean之外的步骤都进行了解析,此篇就继续说下创建bean之前的任务。

    其中spring对创建bean的步骤进行了分类,分别为单例的情况,原型模式的情况和其他情况三种。创建bean的方法都是相同的。处理原型模式和其他都对创建前后对创建bean做了缓存处理。

    这里着重说下单例的情况,其实细节稍微不同外,三种的主要步骤是相同的。

    2、查看常见bean之前的细节

    这里查看getSingleton创建的细节,查看方法 singletonObjects 单例获取。

    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;
    						}
    					});
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里其实有两个主要的步骤,getSingleton 和 createBean。

    2.1、getSingleton 方法解析

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
          // 1.从缓存中获取
          Object singletonObject = this.singletonObjects.get(beanName);
          if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
              throw new BeanCreationNotAllowedException(beanName,
                  "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                  "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }
            if (logger.isDebugEnabled()) {
              logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
            // 2.放入正在创建的缓存对象
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
              this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
              // 3. 从单例工厂Factory中获取,初始化bean
              singletonObject = singletonFactory.getObject();
              newSingleton = true;
            }
            catch (IllegalStateException ex) {
              // Has the singleton object implicitly appeared in the meantime ->
              // if yes, proceed with it since the exception indicates that state.
              
              // 4. 从缓存中再次获取
              singletonObject = this.singletonObjects.get(beanName);
              if (singletonObject == null) {
                throw ex;
              }
            }
            catch (BeanCreationException ex) {
              if (recordSuppressedExceptions) {
                for (Exception suppressedException : this.suppressedExceptions) {
                  ex.addRelatedCause(suppressedException);
                }
              }
              throw ex;
            }
            finally {
              if (recordSuppressedExceptions) {
                this.suppressedExceptions = null;
              }
              // 从正在创建的缓存中移除
              afterSingletonCreation(beanName);
            }
            if (newSingleton) {
              // 放入缓存
              addSingleton(beanName, singletonObject);
            }
          }
          return singletonObject;
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    1. 首先从singletonObjects缓存中获取
    2. 如果没有拿到,那么判断是否需要检测和是否正在创建中,如果是直接报错。
    3. 从传参ObjectFactory的个体Object方法实例化bean
    4. 从正在创建的缓存中移除
    5. 放入缓存,并删除过程中的加载记录
    6. 返回创建结果

    2.2、createBean方法

    进入createBean方法,这里是 AbstractBeanFactory 抽象方法createBean 在 AbstractAutowireCapableBeanFactory 中的实现:

    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    		throws BeanCreationException {
    
    	if (logger.isTraceEnabled()) {
    		logger.trace("Creating instance of bean '" + beanName + "'");
    	}
    	RootBeanDefinition mbdToUse = mbd;
    
    	// Make sure bean class is actually resolved at this point, and
    	// clone the bean definition in case of a dynamically resolved Class
    	// which cannot be stored in the shared merged bean definition.
    
    	// 通过beanName class 获取bean对应的Class对象
    	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    		mbdToUse = new RootBeanDefinition(mbd);
    		mbdToUse.setBeanClass(resolvedClass);
    	}
    
    	// Prepare method overrides.
    	// 检查重写的方法
    	try {
    		mbdToUse.prepareMethodOverrides();
    	}
    	catch (BeanDefinitionValidationException ex) {
    		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    				beanName, "Validation of method overrides failed", ex);
    	}
    
    	try {
    		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    		// 处理BeanPostProcessors 来代理实例
    		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    		if (bean != null) {
    			return bean;
    		}
    	}
    	catch (Throwable ex) {
    		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    				"BeanPostProcessor before instantiation of bean failed", ex);
    	}
    
    	// 创建bean
    	try {
    		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    		if (logger.isTraceEnabled()) {
    			logger.trace("Finished creating instance of bean '" + beanName + "'");
    		}
    		return beanInstance;
    	}
    	catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    		// A previously detected exception with proper bean creation context already,
    		// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
    		throw ex;
    	}
    	catch (Throwable ex) {
    		throw new BeanCreationException(
    				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    1. resolveBeanClass 通过beanName,class 获取bean对应的Class对象。并创建新RootBeanDefinition对象。
    2. mbdToUse.prepareMethodOverrides() 检查重写的方法,这里指的是标签解析的lookup-method 和 replaced-method 对应的方法。
    3. resolveBeforeInstantiation 实例化的前置处理工作,这里其实就是spring aop 功能实现的原理,通过代理在初始化前后做工作,返回的是可能已经是代理类对应的bean。
    4. 真正执行实例化 doCreateBean

    3、总结

    这里总结下这篇文章的内容,在创建bean之前的一些处理。
    主要包括封装新的RootBeanDefinition对象,并把解析的class放入,然后处理重写的方法,之后处理BeanPostProcessor 处理的后置工作,最后进行真正创建bean。

    下篇说下循环依赖的问题,之前的几篇也说了好几次了,下篇就总结说明下。

    希望每天都有所收获,加油!共勉!

  • 相关阅读:
    卷积神经网络 - LeNet
    Linux指令(ls、pwd、cd、touch、mkdir、rm)
    如何把Map的value转为list
    Excel导入数据下载模板示例(备份)
    indexDB & localForage
    golang设计模式——职责链模式
    Redis源码与设计剖析 -- 9.字符串对象
    C. Balanced Bitstring(思维+子字符串规律)
    组件通信$refs | $parent |$root
    MySQL存储引擎
  • 原文地址:https://blog.csdn.net/weixin_42798851/article/details/125901697