spring容器之开启bean的创建之旅

在上篇spring容器之不同scope bean的创建我们在处理原型的过程中遗留了#createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法的讲解,本篇来说一下此方法,该方法为创建bean的入口,直接看代码:
AbstractBeanFactory.java protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException;

这是方法的定义,其中需要三个参数我们分别来说一下参数的用途:
  1. beanName:该参数为创建bean的名字
  2. mbd:合并之后的beanDefinition对象
  3. args:用于构造函数或者工厂方法创建 Bean 实例对象的参数
看完了方法的定义及每个参数的用途,接下来看它的默认实现类
AbstractAutowireCapableBeanFactory
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. //根据rootBeanDefinition和beanName去解析bean的class //1.如果当前bean的class被解析了 //1.1. 克隆一份beanDefinition,主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinition Class resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); }//2.覆盖了RootBeanDefinition的prepareMethodOverrides方法 try { //验证及准备覆盖的方法 mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); }try { //3. 获取一个解析之后的代理bean的实例,而不是真正的bean实例 //给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例 //AOP是基于此处实现的 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); }try { //4.这里才是真正的执行创建bean的方法 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); } }

从代码中我们大致的分为了4个步骤来完成的,这里简单的总结一下
  1. 通过我们的参数rootBeanDefinition和beanName来解析指定的class
//根据rootBeanDefinition和beanName去解析bean的class //1.如果当前bean的class被解析了 //1.1. 克隆一份beanDefinition,主要是因为该动态解析的 class 无法保存到到共享的 BeanDefinition Class resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); }

我们跟踪代码来到:
AbstractBeanFactory.java /** * 1.该方法主要的作用是从bean的定义文件中解析bean的class * 2.将bean类名解析为class的引用 * @param mbd 从合并的beanDefinition来确定bean的class * @param beanName bean的名称 * @param typesToMatch 类型是否匹配 * @return解析后的bean的class文件 * @throws CannotLoadBeanClassException */ @Nullable protected Class resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class... typesToMatch) throws CannotLoadBeanClassException {try { //1.判断是否该bean类型的class,如果是返回class if (mbd.hasBeanClass()) { return mbd.getBeanClass(); } //2. 如果当前解析环境有安全管理器,那么就在此环境下进行bean的class解析 if (System.getSecurityManager() != null) { return AccessController.doPrivileged((PrivilegedExceptionAction>) () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); } //3.没有安全管理器,直接去解析class else { return doResolveBeanClass(mbd, typesToMatch); } } catch (PrivilegedActionException pae) { ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); } }

该方法是解析class的过程,简单的来看一下流程
<1>. 首先通过rootBeanDefinition#hasBeanClass()判断该bean是否有class,有的话返回即可
<2>. 获取当前解析环境的安全管理器,在此环境下进行解析class的操作
private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException { //获取当前上下文的类加载器 ClassLoader beanClassLoader = getBeanClassLoader(); ClassLoader dynamicLoader = beanClassLoader; boolean freshResolve = false; //类型检查 if (!ObjectUtils.isEmpty(typesToMatch)) { // When just doing type checks (i.e. not creating an actual instance yet), // use the specified temporary class loader (e.g. in a weaving scenario). //获取临时的bean的class加载器,用来临时解析bean的class ClassLoader tempClassLoader = getTempClassLoader(); if (tempClassLoader != null) { dynamicLoader = tempClassLoader; freshResolve = true; //tempClassLoader是否是DecoratingClassLoader(用来装饰class加载器)类型的 if (tempClassLoader instanceof DecoratingClassLoader) { DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader; //遍历所有的类型 //获取类型的类名 //通过获取到的类名去从dcl排除添自己加 for (Class typeToMatch : typesToMatch) { dcl.excludeClass(typeToMatch.getName()); } } } } //typesToMatch为null//获取当前bean的class名 String className = mbd.getBeanClassName(); if (className != null) { //对bean进行评估,(可将其解析为对应的表达式)返回其解析的value Object evaluated = evaluateBeanDefinitionString(className, mbd); //evaluated不是className时做处理 if (!className.equals(evaluated)) { // A dynamically resolved expression, supported as of 4.2... //是class类型 if (evaluated instanceof Class) { return (Class) evaluated; } //是String类型 else if (evaluated instanceof String) { className = (String) evaluated; freshResolve = true; } //都不是的话抛IllegalStateException异常 else { throw new IllegalStateException("Invalid class name expression result: " + evaluated); } } //className为null if (freshResolve) { // When resolving against a temporary class loader, exit early in order // to avoid storing the resolved Class in the bean definition. if (dynamicLoader != null) { try { //通过制定class名字去加载class return dynamicLoader.loadClass(className); } catch (ClassNotFoundException ex) { if (logger.isTraceEnabled()) { logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex); } } } //利用反射来构建class对象 return ClassUtils.forName(className, dynamicLoader); } }// Resolve regularly, caching the result in the BeanDefinition... //定期解析,将结果保存到BeanDefinition中 return mbd.resolveBeanClass(beanClassLoader); }

<3>. 在没有安全器时直接解析,解析的过程上面的方法中已经说明,主要是针对于String和class做了处理
  1. 处理override属性
不知道大家还记得之前有篇文章spring容器标签解析之lookup-method和文章spring容器标签解析之replaced-method中我们讲解了spring对lookup-method和replaced-method的解析过程,实际上是将解析中的配置保存到了BeanDefinition的methodOverrides属性中,这里也是同样的类似方法来处理,我们来看代码:
AbstractBeanDefinition.java public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists.if (hasMethodOverrides()) { Set overrides = getMethodOverrides().getOverrides(); //同步枷锁 synchronized (overrides) { //遍历执行prepareMethodOverride方法进行验证 for (MethodOverride mo : overrides) { prepareMethodOverride(mo); } } } }

方法一看很明了,循环执行prepareMethodOverride方法进行处理,我们接着看:
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { //获取对应类中的方法名的个数 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0) { throw new BeanDefinitionValidationException( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); } else if (count == 1) { // Mark override as not overloaded, to avoid the overhead of arg type checking. //进行对MethodOverride没有被覆盖,主要是为了避免参数类型检查的开始 mo.setOverloaded(false); } }

简单的来总结一下:
  • 首先是获取方法名的个数
    -如果count为0,直接抛BeanDefinitionValidationException异常
  • 如果count为1时,设置没有被覆盖的方法
如果当前类只有一个方法,那么就设置重载该方法没有被重载,这样在后续调用的时候便可以直接使用找到的方法,而不需要进行方法的参数匹配验证了.
  1. 实例化的前置处理
我们可以看到的是在真正创建bean之前通过方法#resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)来对BeanDefinition中的属性做些前置处理的操作,我们来看代码:
AbstractAutowireCapableBeanFactory.java //3. 获取一个解析之后的代理bean的实例,而不是真正的bean实例 //给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例 //AOP是基于此处实现的 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; }

上述代码中其实有一个很重要的判断,在我们调用#resolveBeforeInstantiation()后实际上返回的是一个代理对象,并非我们想要的真是对象,如果该代理对象不为null,那么它会直接略过后续的Bean的创建而是直接返回代理结果,很关键的一步,这也是AOP功能基于此处实现的,我们接着看获取代理对象的过程:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; //如果尚未被解析 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { //获取目标的类型 Class targetType = determineTargetType(beanName, mbd); if (targetType != null) { //<1>.前置 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { //<2>.后置 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }

在上面的代码中,最重要的是<1>和<2>的处理过程,那关于如何处理的过程这里不再细究,后续来说.
  • 创建bean的过程
当上面实例化前置处理时如果没有获取到对应的代理对象,那么这里就应该走正常的过程就是bean的创建过程,该过程是通过#doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法来实现,我们来看代码:
/** * 该方法是真正的创建bean的方法 * @param beanName 要创建bean的名称 * @param mbd 定义bean的beanDefinition文件 * @param args 创建bean时,构造方法所需的参数或者是调用bean工厂时来创建bean所需的参数 * @return 完成创建之后的bean的实例 * @throws BeanCreationException */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {//实例化bean的过程 //BeanWrapper是对bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装 bean 的属性描述器 BeanWrapper instanceWrapper = null; //1.如果是单例,从factoryBeanInstanceCache中移除相应的bean实例 if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } //2.根据指定的bean使用对应的策略创建新的实例如:工厂方法、构造函数自动注入、简单初始化 if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } //获取封装实例对象 final Object bean = instanceWrapper.getWrappedInstance(); //获取对应实例对象的类型 Class beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { //将获取到的bean类型赋值给mbd的resolvedTargetType //resolvedTargetType用来保存真实类型bean的类型 mbd.resolvedTargetType = beanType; }// Allow post-processors to modify the merged bean definition. //3.允许后置处理修改mbd synchronized (mbd.postProcessingLock) { //postProcessed默认为false,故不能修改,这里取反表示可以修改 if (!mbd.postProcessed) { try { //后置处理修改beanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } }//4.对单例模式下的循环依赖进行检查 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //避免后期循环依赖,提早曝光创建的bean并加入到addSingletonFactory中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }//初始化bean实例对象 Object exposedObject = bean; try { //5. 给bean的实例填充属性,其中,可能存在依赖于其他bean的属性,然后递归初始化bean的依赖 populateBean(beanName, mbd, instanceWrapper); //6. 调用初始化方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } //7. 引用问题处理,这里先暴露早期单例引用的bean if (earlySingletonExposure) { //从缓存注册中获取,这里不允许早期引用的创建 Object earlySingletonReference = getSingleton(beanName, false); //只有在检测到有依赖的情况下,earlySingletonReference才会不为null if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } //处理依赖 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } }//8. 注册bean try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); }return exposedObject; }

简单的来总结下该方法:
  • 在1处进行是否是单例的判断,如果是需要先清除缓存.
  • 在2处调用#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)方法来实例化bean,于此同时将beanDefinition进行BeanWrapper的转换,其中BeanWrapper是对beanDefinition的包装,位于org.springframework.beans.BeanWrapper包中,详情后续来说.
  • 在3处,MergedBeanDefinitionPostProcessor 的应用.
  • 在4处,单例模式下的循环依赖处理.关于如何处理后面细说.
  • 在5处,给bean进行属性的填充.如何填充后面来说.
  • 在6处,调用 #initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法,初始化 bean .详情见后面
  • 在7处,循环依赖的检查和处理过程.
  • 在8处,完成对DisDisposableBean的注册并返回
【spring容器之开启bean的创建之旅】关于创建的流程我们大致分了又以上8类,在后续的章节中我们分别来说.

    推荐阅读