在容器启动快完成时,会把所有的单例bean进行实例化,也可以叫做预先实例化。
这样做的好处之一是,可以及早地发现问题,及早的抛出异常,及早地解决掉。
本文就来看下整个的实例化过程。其实还是比较繁琐的。
一、从容器中找出所有的bean定义名称
因为不知道谁是单例bean,所以只能先全部找出来。如下图01:
二、循环遍历所有的bean名称,检查是否符合条件
首先要合并bean定义,因为bean定义可以有父子关系,类似继承。
然后这个合并后的bean定义必须是,非抽象的,单例的,非延迟初始化的。
那么它就满足条件,如下图02:
三、判断是否为FactoryBean>类型
如果不是的话,说明该beanName对应一个普通的bean,可以直接实例化。
如果是的话,说明该beanName对应的是一个工厂,这个工厂本身是单例的。
但是它里面生产的bean不一定是单例的。即使是的话,还要判断是否要积极的去初始化工厂里的bean。
具体的判断如下图03:
注:提到FactoryBean>类型,是否想起&符号的作用呢?
四、开始进入众所熟知的getBean(String name)方法
在上一图中可以看到Spring对bean的实例化时竟然是调用的getBean(..)方法。
这样共用一套代码,简单省事。不仅如此,当获取一个bean的依赖时,也可以用该方法。
这样getBean(..)就是一个综合方法,没有bean实例就生成,有的话就直接返回。
如下图04:
五、对手工直接注册的单例对象进行检测
bean实例除了可以用bean定义生成外,还可以由开发人员直接注册一个bean实例。
这样在使用bean定义生成实例前,先使用beanName去手动注册的bean实例集合中找一下。
如下图05:
如果找到了,就不用生成了,否则就会根据bean定义生成bean实例。
六、对FactoryBean>类型的检测
这和上面提到的是一个类型,它是一个工厂,可以认为是包裹在了实际bean实例的外面。
这样可以有一些特殊的作用,不好之处就是每次都要检测下,然后从它内部拿出实际的bean实例。
具体检测过程不再展开,如下图06:
七、对类型进行转换,如果有必要的话
上面我们仅仅是用beanName去手动注册的实例集合中寻找,万一这个手动注册的实例类型和bean定义要求的不兼容呢?
因此要进行类型检测与转换,实在不行就抛异常,如下图07: