Spring源码解析之路 Bean加载篇

245 阅读7分钟

前言

上面一章,说明了bena的解析与注册,这些都是未bean加载做的准备工作,真正复杂的还是bean的加载,但是通过前面的学习,我们也会清楚了各个类在spring容器的职责,这样就可能理解他们的使用,当我们进行扩展时就会更清晰明了,不会看到别人的代码一头雾水,比如下面这段代码的理解

/**
 * 注册bean
 */
public class RegisterBeanFactory implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        // 注册bean  这里就是省略了解析,因为解析实际上就是构建BeanDefinition
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(ProxyBeanFactory.class);
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(beanDefinition, "userDao");
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

上面的代码就是手动注册一个bean到容器中,如果看了之前的文章是不是就很明了了呢,现在我们来看看bean的加载

bean加载

从这段代码开始

    BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
    UserDao userDao = beanFactory.getBean("userDao", UserDao.class);

getbean方法就是加载的开始,真正的实现就是在AbstractBeanFactory类的doGetBean方法

 protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        // 提取对应的beanName
        String beanName = this.transformedBeanName(name);
        // 检查缓存中或者实例工厂中是否有对应的实例
        // 原因是创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
        // Spring的解决方案是不等bean创建完成就会创建bean的ObjectFactory提早曝光
        // 就是将ObjectFactory加入缓存,一旦下一个bean创建时需要依赖上一个bean则直接使用缓存中bean'Factory
        // 直接尝试从缓存获取,或者singletonFactories的ObjectFactory获取
        Object sharedInstance = this.getSingleton(beanName);
        Object beanInstance;
        if (sharedInstance != null && args == null) {
            if (this.logger.isTraceEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            // 只有单例模式下才会尝试解决循环依赖,原型模式下如果存在依赖,那么就会抛出异常
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            // 如果beanDefitionMap找不到beanName则会尝试从parentBeanFactory中找
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
                }

                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                if (requiredType != null) {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }

                return parentBeanFactory.getBean(nameToLookup);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);

            try {
                if (requiredType != null) {
                    beanCreation.tag("beanType", requiredType::toString);
                }
                // 将GenericBeanDefinition转换为RootBeanDefinition,如果指定的bean是子bean那么会合并父bean信息
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                
                String[] dependsOn = mbd.getDependsOn();
                String[] var12;
                // 如存在依赖,就要递归实现依赖的bean
                if (dependsOn != null) {
                    var12 = dependsOn;
                    int var13 = dependsOn.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dep = var12[var14];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 缓存以来调用
                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var31) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var31);
                        }
                    }
                }
                // 实例化依赖的bean后,就开始实例化mbd本身,这个有意思,之前的理解都是本身先实例化
                // 单例模式的创建
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    beanInstance = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    // 原型模式创建
                    var12 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    beanInstance = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    String scopeName = mbd.getScope();
                    if (!StringUtils.hasLength(scopeName)) {
                        throw new IllegalStateException("No scope name defined for bean ��" + beanName + "'");
                    }

                    Scope 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, () -> {
                            this.beforePrototypeCreation(beanName);

                            Object var4;
                            try {
                                var4 = this.createBean(beanName, mbd, args);
                            } finally {
                                this.afterPrototypeCreation(beanName);
                            }

                            return var4;
                        });
                        beanInstance = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var30) {
                        throw new ScopeNotActiveException(beanName, scopeName, var30);
                    }
                }
            } catch (BeansException var32) {
                beanCreation.tag("exception", var32.getClass().toString());
                beanCreation.tag("message", String.valueOf(var32.getMessage()));
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var32;
            } finally {
                beanCreation.end();
            }
        }

        return this.adaptBeanInstance(name, beanInstance, requiredType);
    }

以上代码就是spring加载bean的过程,下面我们来一步步分析一下

  1. 转换对应的beanName

    这部分对应的就是transformedBeanName方法

         /**
         *返回实际的 bean 名称,去掉工厂引用 * 前缀(如果有,也去掉重复的工厂前缀,如果找到)。                 * @param name bean 的名称 * @return 转换后的名称 * @see *BeanFactory#FACTORY_BEAN_PREFIX
          */
         public static String transformedBeanName(String name) {
                 Assert.notNull(name, "'name' must not be null");
                 if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
                         return name;
                 }
                 return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
                         do {
                                 beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
                         }
                         while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
                         return beanName;
                 });
         }
    
     
    

    既然我们之间解析和注册的时候已经明确了beanName那么为什么还要转换呢,从这个方法的注释我们可以知道,beanName有可能有前缀如&,那么这样就要把他去掉,另外我们定义bean的时候可能会用到alias别名,这里的别名就要进行转换,比如别名A指向beanB,那么别名A要返回beanB

  2. 尝试从缓存中加载依赖

    这部分主要是为了解决循环依赖,单例的情况下,解决依赖的方式就是,在spring bean还没加载完,就将他里面的对象先放到缓存中ObjectFactory,读取的时候如果缓存里面有就从缓存里面读取,如果没有就从singletonFactories中读取。

  3. bean的实例化

    这一步时我们可能有一个疑问,bean不是已经在解析和注册时已经实例化到缓存BeanDefinitionResitry中了吗?为什么还要再实例化,那是因为解析和注册后我们得到的是初始状态的bean,而我们真正需要的bean是facoty-mthod返回的bean,他的创建是由getObjectForBeanInstance方法来完成的

  4. 原型模式下判断循环依赖

    spring会对循环依赖处理都是在单例模式下,如果原型模式出现了这种情况会直接抛出异常

  5. 检测parentBeanFactory

    如果当前的缓存中没有找到beanName的配置,那么就去parentBeanFactory中查找,找到后再通过递归调用getBean方法。

  6. 存储xml文件的GernericBeanDefinition转换为RootBeanDefinition

    spring的后续处理都是针对RootBeanDefinition进行处理的,所以我们要把解析后的GernericBeanDefinition转换成RootBeanDefinition

  7. 寻找依赖

    spring bean的创建过程中,要先创建bean中的属性,比如depends-on="jedisPoolConfig"

    <!-- jedis pool配置 -->
    <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy" depends-on="jedisPoolConfig">
     <constructor-arg ref="jedisPoolConfig" />  
     <constructor-arg value="127.0.0.1" />  
     <constructor-arg type="int" value="6379" />  
    </bean>
    

depends-on="jedisPoolConfig" 在实例话前加载

  1. 针对不同的scope进行加载

    singleton,prototype,request多种scope

获取单例bean

从前面的代码中了解到,单例在spring容器只会创建一次,后续都是从缓存或者singletonFactoty中获取,为了解决循环依赖,spring会在不等bean创建完成就将创建bena的beanFactory提早曝光,下面看看他的实现 getSingleton方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
                Assert.notNull(beanName, "Bean name must not be null");
                // 锁定全局变量并进行处理
                synchronized (this.singletonObjects) {
                        // 缓存中是否存在实例
                        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 + "'");
                                }
                                beforeSingletonCreation(beanName);
                                boolean newSingleton = false;
                                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                                if (recordSuppressedExceptions) {
                                        this.suppressedExceptions = new LinkedHashSet<>();
                                }
                                try {   
                                        // 调用预先设定的getObjct方法
                                        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.
                                        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;
                }
}

从bean实例中获取对象

在这一步前面的过程分别是 解析-注册-从不同的scope中获取bean,那么这一步就是终极加载,前面的流程中获得的bean其实都是初始状态的bean,而这一步就是要在前面的基础上加料了,这一步对应的方法就是getObjectForBeanInstance方法

protected Object getObjectForBeanInstance(
                        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

                // 如果指定的name是工厂相关&前缀,且beanInstace又不是Factory则验证不通过
      
                if (BeanFactoryUtils.isFactoryDereference(name)) {
                        if (beanInstance instanceof NullBean) {
                                return beanInstance;
                        }
                        if (!(beanInstance instanceof FactoryBean)) {
                                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
                        }
                        if (mbd != null) {
                                mbd.isFactoryBean = true;
                        }
                        return beanInstance;
                }

                // Now we have the bean instance, which may be a normal bean or a FactoryBean.
                // If it's a FactoryBean, we use it to create a bean instance, unless the
                // caller actually wants a reference to the factory.
                if (!(beanInstance instanceof FactoryBean)) {
                        return beanInstance;
                }

                Object object = null;
                if (mbd != null) {
                        mbd.isFactoryBean = true;
                }
                else {  
                        // 尝试从缓存中加载
                        object = getCachedObjectForFactoryBean(beanName);
                }
                if (object == null) {
                        // Return bean instance from factory. 明确知道beanInstance是Factory类型
                        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
                        // Caches object obtained from FactoryBean if it is a singleton.
                        if (mbd == null && containsBeanDefinition(beanName)) {
                                // 父类合并
                                mbd = getMergedLocalBeanDefinition(beanName);
                        }
                        boolean synthetic = (mbd != null && mbd.isSynthetic());
                        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
                }
                return object;
        }
        

主要工作就是

  • 对FactoryBean进行验证

  • 对非FactoryBean不做处理

  • 对bean进行转换

  • 最后委托给getObjectFromFactoryBean方法

        protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
               if (factory.isSingleton() && containsSingleton(beanName)) {
                       synchronized (getSingletonMutex()) {
                               Object object = this.factoryBeanObjectCache.get(beanName);
                               if (object == null) {
                                       object = doGetObjectFromFactoryBean(factory, beanName);
                                       // Only post-process and store if not put there already during getObject() call above
                                       // (e.g. because of circular reference processing triggered by custom getBean calls)
                                       Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                                       if (alreadyThere != null) {
                                               object = alreadyThere;
                                       }
                                       else {
                                               if (shouldPostProcess) {
                                                       if (isSingletonCurrentlyInCreation(beanName)) {
                                                               // Temporarily return non-post-processed object, not storing it yet..
                                                               return object;
                                                       }
                                                       beforeSingletonCreation(beanName);
                                                       try {
                                                               object = postProcessObjectFromFactoryBean(object, beanName);
                                                       }
                                                       catch (Throwable ex) {
                                                               throw new BeanCreationException(beanName,
                                                                               "Post-processing of FactoryBean's singleton object failed", ex);
                                                       }
                                                       finally {
                                                               afterSingletonCreation(beanName);
                                                       }
                                               }
                                               if (containsSingleton(beanName)) {
                                                       this.factoryBeanObjectCache.put(beanName, object);
                                               }
                                       }
                               }
                               return object;
                       }
               }
               else {
                       // 这里面直接调动了FactotyBean的getObject方法
                       Object object = doGetObjectFromFactoryBean(factory, beanName);
                       if (shouldPostProcess) {
                               try {   
                                       // 调用ObjectFactory的后置处理器
                                       object = postProcessObjectFromFactoryBean(object, beanName);
                               }
                               catch (Throwable ex) {
                                       throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                               }
                       }
                       return object;
               }
       }
    

从代码中可以看出,其实在加载完bean后又执行了一个调用后置处理器的操作,这个操作就是为了以后对spring加载bean的灵活拓展

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}