Spring核心IOC源码解读(四)getBean创建SpringBean对象以及循环依赖问题

  getBean方法会调用到 AbstractBeanFactory 的 doGetBean() 方法中去。下面看看 AbstractBeanFactory  的类图结构

 

 一、AbstractBeanFactory doGetBean()方法

  这个代码块比较主要点在 getSingleton() 方法上

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

    ...
    // 1.尝试获取单例对象
    Object sharedInstance = getSingleton(beanName);
    ...

    // 2.创建对象并获取单例对象
    if (mbd.isSingleton()) {
        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;
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }

    ...

    return (T) bean;
}

  下面是第1步中 getSingleton() 的具体代码

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //尝试从缓存C中获取单例对象
    Object singletonObject = this.singletonObjects.get(beanName);
    //为获取到并且对象在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            //从早期缓存A中获取对象
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //获取对象
                    singletonObject = singletonFactory.getObject();
                    //放入早期缓存A
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //清除该对象的单例工厂缓存B
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

  下面是第2步中  getSingleton() 的具体代码

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        //从缓存C中获取
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
//标记当前对象正在创建
beforeSingletonCreation(beanName); ...
//调用实现类的createBean方法 singletonObject = singletonFactory.getObject(); newSingleton = true; ... //如果是单例则做对应的缓存操作 if (newSingleton) { addSingleton(beanName, singletonObject); }
//清除当前正在创建的缓存
afterSingletonCreation(beanName); }
return singletonObject; } } protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { //缓存C this.singletonObjects.put(beanName, singletonObject); //清除缓存B this.singletonFactories.remove(beanName); //清除缓存A this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }

 

二、AbstractBeanFactory createBean()方法,创建SpringBean对象的实现

  createBean方法是一个抽象方法,由实现类实现,下面是实现类的结构

 

   这个实现类createBean方法实现如下,首先获取Class对象,再处理 InstantiationAwareBeanPostProcessor 接口的实现,然后创建Bean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    
    RootBeanDefinition mbdToUse = mbd;
    //获得Bean的Class对象
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    //执行 InstantiationAwareBeanPostProcessor 接口的实现
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
        return bean;
    }
    //创建Bean
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    if (logger.isTraceEnabled()) {
        logger.trace("Finished creating instance of bean '" + beanName + "'");
    }
    return beanInstance;
    
}

   doCreateBean方法包含了,通过反射创建对象,填充对象成员变量等操作👇,填充对象又会通过BeanFactory进行getBean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

    // 1.通过反射构建对象,并使用包装类将Bean包装起来
    BeanWrapper instanceWrapper = null;
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        //2.缓存Bean
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    //3.填充Bean的成员变量
    populateBean(beanName, mbd, instanceWrapper);
    exposedObject = initializeBean(beanName, exposedObject, mbd);
    ...
    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            //缓存B
            this.singletonFactories.put(beanName, singletonFactory);
            //清除缓存A
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

 

 三、循环引用问题

  比如甲引用了乙,而乙又引用了甲,这时候Spring会怎么办呢?

  假设是先创建甲的对象。Spring大致会做以下步骤:

  为了方便理解,BeanFactory中的一些缓存先起别名:

//缓存C 用于缓存已经构建好的单例对象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//缓存B 用于缓存构建对象的工厂
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
//缓存A 用于缓存循环引用早期构建的对象
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//缓存D 用于缓存当前对象已经进入构建状态
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

  (1)第一步:在构建甲对象之前,先将BeanName缓存到D中;

  (2)第二步:构建甲的对象,将甲的对象工厂放入B缓存;

  (3)第三步:填充甲的成员变量乙,乙也重复甲上述动作;

  (4)第四步:在乙填充成员变量甲的时候,这时候会去获取甲的对象;

  (5)第五步:这时候获取甲对象,先从C缓存取,没取到,则从A缓存取,再没取到,则从D缓存取并判断甲正在创建,于是从B缓存取出对象工厂,并获得了甲的对象,然后缓存到A中,并清除甲对象的B缓存;

  (6)第六步:这时候乙对象构建好了,成员变量甲也赋值上了,这时候甲的成员变量乙也赋值上了,最后放入缓存C,清除缓存A、B和D

  (7)如下图,执行顺序就是图的顺序,先addSingletonFacotry,再getSingleton,最后addSingleton

 

 

 

 

posted on 2020-11-07 15:06  lyjlyjlyj  阅读(174)  评论(0编辑  收藏  举报

导航