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