Spring 获取Bean流程

开篇

 在Spring 加载BeanDefinition文章中我们已经Spring如何加载xml文件并扫描注解class文件生成BeanDefinition,在这篇文章中我们着重梳理下GetBean过程。

 文章的整体思路在于ClassPathXmlApplicationContext通过到DefaultListableBeanFactory查找Bean对应的BeanDefinition后创建Bean对象


时序图

Spring 获取Bean流程_第1张图片
GetBean

说明:

  • 核心调用链路使ClassPathXmlApplicationContext -> DefaultListableBeanFactory。
  • DefaultListableBeanFactory保存的是从xml文件加载的BeanDefinition对象。



Spring 获取Bean流程_第2张图片
ClassPathXmlApplicationContext

说明:

  • ClassPathXmlApplicationContext的类依赖图,用于补充说明上图的调用链。



Spring 获取Bean流程_第3张图片
DefaultListableBeanFactory

说明:

  • DefaultListableBeanFactory的类依赖图,用于补充说明上图的调用链。


Bean获取源码分析

 public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
        SimpleBean simpleBean = applicationContext.getBean(SimpleBean.class);
}

说明:

  • 1、通过创建ClassPathXmlApplicationContext对象加载xml文件。
  • 2、通过applicationContext.getBean()返回bean对象。


public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {

    public Object getBean(String name) throws BeansException {
        assertBeanFactoryActive();
        return getBeanFactory().getBean(name);
    }
}

说明:

  • 3、ClassPathXmlApplicationContext.getBean()通过基类AbstractApplicationContext来实现。
  • 4、AbstractBeanFactory.getBean()方法继续跟进Bean对象。


public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    protected  T doGetBean(final String name, @Nullable final Class requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        final String beanName = transformedBeanName(name);
        Object bean;

        // 处理单例 情况 Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        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.
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            //合并BeanDefinition信息
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
            // 标记beanName正在创建
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // 处理依赖的bean率先创建
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // 区分不同的类型的Bean实例并进行创建
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);

                    try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                    }
                }
            }
            catch (BeansException ex) {
            }
        }

        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
            }
        }
        return (T) bean;
    }
}

说明:

  • 5、AbstractBeanFactory.getBean()负责返回Bean对象,按照一定的逻辑进行获取返回。
  • 6、如果单例Bean已经存在那么就直接返回单例Bean。
  • 7、如果Bean不存在就先合并BeanDefinition信息。
  • 8、先创建Bean依赖的Bean对象
  • 9、区分不同的Bean类型创建Bean对象。
    单例(singleton) IOC容器中有且只有一个对象,多次调用getBean返回同一个对象
    多例(prototype) 每次调用getBean返回一个新对象
    HTTP Request 每次HTTP请求共用同一个对象
    HTTP Session 每个HTTP会话共用同一个对象
    Application ServletContext共用一个对象


单例Bean获取逻辑

/** Cache of singleton objects: bean name --> bean instance */
private final Map singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name --> bean instance */
private final Map earlySingletonObjects = new HashMap<>(16);


public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
}

说明:

  • 10、getSingleton() 整个过程如下:首先从一级缓存 singletonObjects 获取,如果没有且当前指定的 beanName 正在创建,就再从二级缓存中 earlySingletonObjects 获取,如果还是没有获取到且运行 singletonFactories 通过 getObject() 获取,则从三级缓存 singletonFactories 获取,如果获取到则,通过其 getObject() 获取对象,并将其加入到二级缓存 earlySingletonObjects 中 从三级缓存 singletonFactories 删除

  • 11、Bean创建完成了初始化的第一步并且将自己提前曝光到singletonFactories中,用于解决相互依赖问题。

  • singletonObjects:单例对象的cache

  • singletonFactories : 单例对象工厂的cache

  • earlySingletonObjects :提前曝光的单例对象的Cache


参考文章

Spring源码初探-IOC(4)-Bean的初始化-循环依赖的解决

你可能感兴趣的:(Spring 获取Bean流程)