您当前的位置: 首页 >  spring

止步前行

暂无认证

  • 0浏览

    0关注

    247博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring源码系列(七)——Bean的实例化和初始化过程

止步前行 发布时间:2021-11-04 15:10:52 ,浏览量:0

文章目录
  • 一、getBean()
  • 二、第一次调用getSingleton()
  • 三、第二次调用getSingleton()
  • 四、createBean()
  • 五、doCreateBean()
  • 六、createBeanInstance()
  • 七、autowireConstructor()
  • 八、populateBean()
  • 九、initializeBean()
  • 十. invokeInitMethods()
  • 十一、小结

https://blog.csdn.net/zxd1435513775/article/details/120935494?spm=1001.2014.3001.5501

Spring源码系列(四)——ConfigurationClassPostProcessor功能解析

https://blog.csdn.net/zxd1435513775/article/details/121113933?spm=1001.2014.3001.5501

Spring源码系列(六)——容器的刷新(下)

在第四篇和第六篇中,都分析到了一个方法,就是getBean(),这行代码的意思是:从容器中获取Bean,如果没有,则去创建Bean。所以在查看Spring源码时,只要看到这个方法,就要知道是去实例化Bean了。

这个方法的具体实现位于AbstractBeanFactory类中,下面就来分析吧。

一、getBean()

下面来看一下这个方法的详细代码:

// 根据name去获取对应的Bean实例
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

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

   /**
	* 下面这个方法是通过 name 去获取 beanName,这里为什么不使用 name 直接作为 beanName呢?
	* 有两个原因:
	* 1、name 的值可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean 实现类所创建的 bean。
	* 在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储方式是一致的,即 ,而 beanName 中是没有 & 这个字符的。
	* 所以需要将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。
	* 2、还是别名的问题,转换需要 &beanName
	*/
    String beanName = transformedBeanName(name);
    Object bean;

   /**
	* 下面这个getSingleton()方法,在上面getBean()的时候也会调用,在Bean初始化的时候会调用
	* 为什么需要这么做呢?
	* 也就是说Spring容器在Bean初始化的时候先获取这个Bean对象,判断这个对象是否被实例化好了,
	* 是不是已经被创建了。普通情况下绝对为空,但有一种情况可能不为空
	* 从Spring容器中获取一个Bean,由于Spring中Bean容器是用一个map(singletonObjects)来存储的
	* 所以可以理解getSingleton(beanName)等于beanMap.get(beanName)
	* 由于getBean()方法会在Spring环境初始化的时候(就是对象被创建的时候调用一次)调用一次
	* 还会在Bean初始化的时候再调用一次
	* 此处为getSingleton()第一次调用,意思是去缓存里查询该beanName有没有被创建
	*/
    Object sharedInstance = getSingleton(beanName); // 此方法详解,看下面第二部分
    
    // 此处拿到sharedInstance,不为空,表示已经实例化了,但属性有没有填充不确定
    // 在分析FactoryBean的时候,分析了getObjectForBeanInstance()方法,下面我们就分析else的情况
    if (sharedInstance != null && args == null) {
       /**
		* 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。
		* 但如果 sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的
		* bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回即可。
		* 毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
		*/
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    } else {

        // 判断是否是原型Bean,如果是原型,不应该在Spring容器初始化的时候创建
        // 为什么要直接抛异常呢?因为在refresh()方法中的finishBeanFactoryInitialization()方法中
        // 已经对bean进行了判断,BeanDefinition不是抽象的,不是懒加载的,是单列的才会进入执行到此处
        // 所以会抛异常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 检查Spring工厂中是否存在bean定义
        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 {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        // 此参数为方法传入进来
        if (!typeCheckOnly) {
            // 添加到alreadyCreated set集合当中,表示他已经创建过一次
            markBeanAsCreated(beanName);
        }

        try {
            // 如果给的bean的定义是有父类的,则通过与父bean合并,返回给定顶级bean的RootBeanDefinition。
            // 在使用xml配置Bean时,有个属性parent属性来指定父类
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 再次检查,检查合并后的bean是不是抽象的
            checkMergedBeanDefinition(mbd, beanName, args);

			// 获取所依赖的bean,保证对当前bean所依赖的bean进行实例化。
            // 此处的意思是,被依赖的Bean要先进行实例化
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                    	// 抛异常代码略
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        // 又一次调用getBean()方法,此处获取的依赖bean,递归调用,获取即创建
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                    	// 抛异常代码略
                    }
                }
            }

            // 此处才开始创建Bean,也是此处进行了getSingleton()方法的第二次调用
            if (mbd.isSingleton()) {
                // 此处为getSingleton()第二次调用,两处调用,形参不一样
                // 先执行getSingleton()方法,在该方法中,可以调用lamda表达式
                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();
                if (!StringUtils.hasLength(scopeName)) {
                    // 抛异常代码略
                }
                Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    // 抛异常代码略
                }
                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) {
            cleanupAfterBeanCreationFailure(beanName);
            throw 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) {
                // 抛异常代码略
            }
            return convertedBean;
        } catch (TypeMismatchException ex) {
            // 抛异常代码略
        }
    }
    return (T) bean;
}
二、第一次调用getSingleton()

下面来看下这个方法详细代码:DefaultSingletonBeanRegistry类中

// 第一处getSingleton()是调用这个方法,根据beanName去singletonObjects中查询是否已经被实例化
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    // 从singletonObjects中获取bean,如果不为空直接返回,不再进行实例化工作
    Object singletonObject = this.singletonObjects.get(beanName);
    
    // isSingletonCurrentlyInCreation()方法判断当前beanName是不是正在创建中
    // 如果为null并且正在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            
            // 去earlySingletonObjects中拿,注意这行集合里面存放的对象还没有被填充属性
            singletonObject = this.earlySingletonObjects.get(beanName);
            
            // 如果也没拿到,说明还没有创建完成
            if (singletonObject == null && allowEarlyReference) {
                
                // 去存放Bean工厂的集合里拿,看看是不是Bean工厂
                ObjectFactory singletonFactory = 
                    this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // 此集合是为了解决循环引用问题
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

public boolean isSingletonCurrentlyInCreation(String beanName) {
    // 正在创建的Bean会被放到这个singletonsCurrentlyInCreation集合中
    return this.singletonsCurrentlyInCreation.contains(beanName);
}

这里要特别说一下singletonObjectsearlySingletonObjectssingletonsCurrentlyInCreationsingletonFactories四个作用,很关键!!!

  • singletonObjects是个Map,用于存放完全初始化好的 Bean,从这个Map中取出的 Bean可以直接使用
  • earlySingletonObjects是个Map,用于存放原始的Bean对象,用于解决Bean的循环依赖问题,注意:存到里面的对象还没有被填充属性,即还没有完成初始化!!!
  • singletonsCurrentlyInCreation是个Set,用于存放正在创建中的Bean
  • singletonFactories是个Map
关注
打赏
1657848381
查看更多评论
0.0758s