揭秘Spring(六)之复盘分析Bean的加载

前边我们吭哧吭哧的说了一堆bean加载过程中可能的扩展方式,在本节中,我们就从源码的角度详细分析下bean的加载过程。

需要提前说明的是,为了便于阅读以及限于篇幅,我展示的代码可能会对源码做出了部分删除省略,当然,相应处都会标记,如果感兴趣的话,可以自己对比源码阅读。

getBean()

Account account=(Account) beanFactory.getBean("account");
复制代码

我们可以通过beanFactory的getBean()方法来获得需要的bean

public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
}
复制代码

接着调用doGetBean

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = this.transformedBeanName(name);
        
        // 尝试获取单例Bean,注意循环依赖问题
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        
        // sharedInstance不为null即此时是单例模式且缓存中已存在bean,直接从缓存中获取bean
        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 + "'");
                }
            }

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        // 此时是原型模式或者单例模式但是缓存中还不存在bean
        } else {
            // 此时存在循环依赖,然而原型模式直接抛出异常,这个异常名字也很好理解, bean正在创建状态
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            
            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            // 从当前加载的配置中找不到 beanname,此时递归去parentFactory查找
            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);
            }

            try {
                RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                // 递归实例化依赖的bean
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        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 var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }
                // 单例模式,此时需要我们去从头创建bean
                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                // 原型模式
                } else if (mbd.isPrototype()) {
                    var11 = null;

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

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                // 别的Scope的处理情况
                } else {
                    // something
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }
        // 检查需要的类型是否符合bean的实际类型
        //  some code here 
        return bean;
    }
复制代码

这个代码相当长,我也只是在关键点做了些必要的注释,一次性看不懂没关系,先往后看

首先理一下:

  1. 尝试获取单例Bean,获取成功的话直接返回,不成功说明缓存中没有
  2. 此时不管是原型模式还是单例模式都需要去从头创建bean
  3. 不管单例还是原型,我们都提到了循环依赖,先记得这个东西,后边再说
  4. 当前配置中不包含beanName时,递归去parentBeanFactory查找
  5. 生成beandefinition
  6. 递归实例化依赖的bean
  7. 根据不同Scope创建bean

从缓存获取单例bean

Object sharedInstance = this.getSingleton(beanName);

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

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        
        // 检查缓存中是否有bean, singletonObjects是个Map<beanName,beanInstance>
        Object singletonObject = this.singletonObjects.get(beanName);
        // 缓存中没有且该bean正处于创建状态
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            // 定全局变量
            synchronized(this.singletonObjects) {
            
                // earlySingletonObjects 放置用于提前曝光的ObjectFactory,该ObjecFactory可生成对应bean
                singletonObject = this.earlySingletonObjects.get(beanName);
                
                //  singletonObject 若不为空说明此时正在加载,直接返回即可
                // 某些方法需要提前初始化时候会调用 addSingletonFactory 将对应ObjectFactory 存入 singletonFactories
                if (singletonObject == null && allowEarlyReference) {
                
                    // singletonFactories是个Map<beanName,ObjectFactory>
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        singletonObject = singletonFactory.getObject();
                        
                        // 记录在 earlySingletonObjects,同时清除 singletonFactories 中的记录,二者互斥
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject;
}
复制代码
  1. 首先尝试从singletonObjects 中获取实例,成功直接返回
  2. singletonObjects 中没有实例且该bean正在创建中,从 singletonFactories 中找beanName 对应的 ObjectFactory
  3. 调用ObjectFactory 获取bean,并放入earlySingletonObjects, 从singletonFactories中 remove该ObjectFactory

如果当前是第一次来获取创建中的实例的话,需要去singletonFactory获取ObjectFactory,后续就可以不用这么麻烦,直接从earlySingletonObjects中获取,当实例创建完成后,就更简单了,直接从 singletonObjecs中获取。如果你现在不太明白这段话,往后读吧,一会儿回头来看就懂了。

循环依赖

循环依赖是个什么东西呢?

我们知道Spring可以很方便实现bean实例的注入,比如我们想要A a,结果A中有个B类的实例,所以Spring就需要去找到B的实例来注入,结果B中又有一个A a的属性,Spring又要去找A的实例,得,问题又回到原点,这就是循环依赖

循环依赖只有在单例模式下才可以解决,原型模式只能抛出异常

单例模式循环依赖

@Component
public class B {

    @Autowired
    A a;

    public B(A a){
        this.a=a;
    }

    public void setA(A a) {
        this.a = a;
    }
}
复制代码
@Component
public class A {
    @Autowired
    B b;

    public void setB(B b) {
        this.b = b;
    }

    public A(B b){
        this.b=b;
    }
}
复制代码
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringdemoApplication.class)
public class UserTest{
    @Test
    public void tt(){
    }
}
复制代码
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException
复制代码

这就是一个很典型的循环依赖,可以看到抛出BeanCurrentlyInCreationException,即bean正在创建中。正如我们上边所说A中需要B,去创建B的实例,结果发现B中需要A,去找A发现A还在创建中,抛出异常。

解决方案很简单,去掉有参构造器,只保留setter。这样的话,Spring会首先由ObjectFactory得到一个刚初始化还没填充属性的A的实例,接着A需要B的实例,Spring去创建B的实例的过程,再接着B中需要A的实例,就把刚那个A的实例拿过来,注意B中的A的地址和刚刚那个A地址一样,所以后续填充完A的属性后,B中的A也就有了属性,看不太懂还是没关系,继续看,最后回来看。

原型模式循环依赖

原型模式中因为spring不会缓存bean,所以无法做到提前暴露,也因此无法解决循环依赖

好了,说完循环依赖我们再回归正题,

如果能得到不为空的singletonObject,紧接着来到getObjectForBeanInstance ,我们前边第一节讲过的FactoryBean派上用场了,这个方法就是判断当前获得的shareInstance是否是FactoryBean类,如果是的话返回 getObject().

bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
复制代码
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {       // 如果指定name以&为前缀,此时应返回factoryBean本身的实例
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            // 实例是null直接返回null
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            // 实例不是FactoryBean类型,直接抛出异常
            } else if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            } else {
                if (mbd != null) {
                    mbd.isFactoryBean = true;
                }
                // 返回factoryBean本身的实例
                return beanInstance;
            }
            
        // 实例不是FactoryBean类型的,直接返回
        } else if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        // 实例是FactoryBean类型的,且name并不存在&前缀
        } else {
            Object object = null;
            if (mbd != null) {
                mbd.isFactoryBean = true;
            } else {
                // 直接从缓存中获取
                object = this.getCachedObjectForFactoryBean(beanName);
            }
            // 此时的bean就是factoryBean,而且我们要的实例是该工厂Bean所生产的
            if (object == null) {
                FactoryBean<?> factory = (FactoryBean)beanInstance;
                if (mbd == null && this.containsBeanDefinition(beanName)) {
                    mbd = this.getMergedLocalBeanDefinition(beanName);
                }
                // 是系统定义还是用户定义的bean
                boolean synthetic = mbd != null && mbd.isSynthetic();
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }

            return object;
        }
}
复制代码

上述代码主要完成了对前一步生成的bean的实例做一些解析工作

  1. 实例需要的是FactoryBean本身所对应的bean,返回工厂bean
  2. 获取的bean跟工厂bean没关系,返回bean
  3. 从工厂bean中获得其所生产的bean(getObject)或者从缓存中获取

获取单例

说了这么多…其实我们才说完从缓存中怎么获取单例,万一缓存中不存在呢?我们就需要去创建bean了,即从头开始bean的加载,当然,原型模式也是需要从头创建的

sharedInstance = this.getSingleton(beanName, () -> {
                        try {
                            return this.createBean(beanName, mbd, args);
                        } catch (BeansException var5) {
                            this.destroySingleton(beanName);
                            throw var5;
                        }
                    });
复制代码

这里调用的是getSingleton的一个重载方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized(this.singletonObjects) {
            // 确保缓存中还是没有该bean
            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 (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                
                // 获得实例前记录加载状态,检测循环依赖
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    
                    // 此时bean加载结束,移除缓存中对bean正在加载状态的记录
                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }
复制代码

其实这么一大串代码,无非就实现了try中的那两行代码,singletonObject = singletonFactory.getObject(),得到实例,最后返回。同时,返回上上段代码,我们其实可以发现,这一句话的功能其实是由 createBean 方法实现的,如下代码所示。

@FunctionalInterface
public interface ObjectFactory<T> {
    T getObject() throws BeansException;
}
复制代码

这里涉及到java8的函数式编程,不是本文重点,不再赘述

注意在得到实例的前后对一些辅助状态的操作,同时成功得到实例后会将newSingleton标记设为true,在整个代码的最后,finally阶段,如果newSingleton为true,会使用addSingleton 操作,将实例bean放入缓存,同时将singletonFactories和 earlySingletonObject 中benaName对应内容清空。

protected void beforeSingletonCreation(String beanName) {
        // singletonsCurrentlyInCreation 中放入beanName
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
}

protected void afterSingletonCreation(String beanName) {
        // singletonsCurrentlyInCreation 中移除beanName
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
}

protected void addSingleton(String beanName, Object singletonObject) {
        synchronized(this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
}
复制代码
  • 这个before方法主要是将 beanName 加入 singletonsCurrentlyInCreation ,即将当前正在创建的bean记录到缓存中
  • after方法则是将beanName从 singletonsCurrentlyInCreation 清除
  • 最后实例化完成后将结果记录到缓存然后清除一些创建过程中的辅助状态

处理完前后的一些状态,紧接着来看下到底是怎么样创建bean的吧

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Creating instance of bean '" + beanName + "'");
        }

        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        try {
            mbdToUse.prepareMethodOverrides();
        } catch (BeanDefinitionValidationException var9) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", var9);
        }

        Object beanInstance;
        try {
        
            // BeanPostProcessor在这里可以返回代理,实现短路
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            
            // 如果我们实现了BeanPostProcessor 扩展,这里直接返回代理实现短路效果,AOP正是基于此处
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var10) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var10);
        }

        try {
            // 正常的创建bean
            beanInstance = this.doCreateBean(beanName, mbdToUse, args);
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Finished creating instance of bean '" + beanName + "'");
            }

            return beanInstance;
        } catch (ImplicitlyAppearedSingletonException | BeanCreationException var7) {
            throw var7;
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", var8);
        }
    }
复制代码

resolveBeforeInstantiation 使得在初始化前实现短路,其实就是加了BeanPostProcessor。 如果有BeanPostProcessor可以在这里实现修改bean,直接短路返回,不需要后边的正常的创建bean。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            
            // 注意是 InstantiationAwareBeanPostProcessors
            if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
                Class<?> targetType = this.determineTargetType(beanName, mbd);
                if (targetType != null) {
                    bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
                        bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }

            mbd.beforeInstantiationResolved = bean != null;
        }

        return bean;
}
复制代码

注意这个方法中的applyBeanPostProcessorsBeforeInstantiation 和 applyBeanPostProcessorsAfterInitialization,其实就是beanpostProcessor

可以看到主要是通过 InstantiationAwareBeanPostProcessors 的postprocessBeforeInstantiation 实现bean的前处理 和 BeanPostprocessor 的 postProcessAfterInitialization 实现bean的后处理

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;

        Object current;
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
        }

        return result;
}

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;

        Object current;
        for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
            BeanPostProcessor processor = (BeanPostProcessor)var4.next();
            current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
        }

        return result;
}
复制代码

正常的创建bean如下所示,此时没有被短路

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }

        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        Object bean = instanceWrapper.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }
        
        // 是否需要提前曝光 : 单例&允许循环依赖&当前bean正在创建中 
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }
            
            // 避免循环依赖,在bean初始化完成前将ObjectFcatory放入工厂
            this.addSingletonFactory(beanName, () -> {
                // 应用BeanPostProcessor
                // AOP即在这里将advice动态织入bean中,没有BeanPostProcessor的话直接返回bean
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = this.getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                } else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
                    String[] dependentBeans = this.getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
                    String[] var12 = dependentBeans;
                    int var13 = dependentBeans.length;

                    for(int var14 = 0; var14 < var13; ++var14) {
                        String dependentBean = var12[var14];
                        if (!this.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.");
                    }
                }
            }
        }

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }
复制代码

注意这里边的addSingletonFactory,避免循环依赖

另外跟前边一样,这里的bean最终是通过getEarlyBeanReference 得到的。

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(singletonFactory, "Singleton factory must not be null");
        synchronized(this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory);
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }
复制代码

有没有发现什么,singletonFactories 在这里放入(beanName,ObjectFactory),同时earlySingletonObject移除掉(beanName,Object),此时是创建中嘛,对应我们上边说的从singletonFactories中得到一个ObjectFactory

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Iterator var5 = this.getBeanPostProcessors().iterator();

            while(var5.hasNext()) {
                BeanPostProcessor bp = (BeanPostProcessor)var5.next();
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor)bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
}
复制代码

看有没有BeanPostProcessor,做相应的处理,否则直接返回本来的bean,这里的 beanpostprocessor 是 SmartInstantiationAwareBeanPostProcessor。

从ApplicationContext中再串一遍

到此为止,算是勉强串起来了,但是总是感觉不舒服。也罢,我们找个舒服的姿势,目光转向ApplicationContext,我们在第一节中说过了BeanFactory和ApplicationContext,还记得吧~

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
        if (refresh) {
            this.refresh();
        }
}
复制代码
public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            // 准备上下文环境
            this.prepareRefresh();
            // 初始化BeanFactory
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 对BeanFactory 进行功能填充扩展
            this.prepareBeanFactory(beanFactory);

            try {
                // 子类覆盖做额外处理
                this.postProcessBeanFactory(beanFactory);
                // 激活各种BeanFactory处理器
                this.invokeBeanFactoryPostProcessors(beanFactory);
                // 注册拦截bean创建的bean处理器,调用是在getBean的时候,注意BeanFactory必须手动注册
                this.registerBeanPostProcessors(beanFactory);
                
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                // 完成非延迟加载的bean的加载,提前调用getBean,进而调用beanpostProcessor
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }
        }
}
复制代码

总结

至此,勉勉强强把我们前边说过的一些扩展组件通过bean的加载串了一遍,我也是初学者水平,难免有些理解不到之处,若有错误,多多指正~


公众号

揭秘Spring(六)之复盘分析Bean的加载

原文 

https://juejin.im/post/5dcc025d6fb9a02b5e7249bf

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 揭秘Spring(六)之复盘分析Bean的加载

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址