本文基于spring-5.2.5
spring加载bean的大致过程如下:
(1)转换对应beanName;
(2)尝试从缓存中加载单例;
(3)原型模式的依赖检查;
(4)检测parentBeanFactory;
(5)将存储xml配置文件的GernericBeanDefinition转换成RootBeanDefinition;
(6)寻找依赖;
(7)针对不同的scope进行bean的创建;
(8)bean的类型转换;
下面从读取下图获取bean开始。
点击进入getBean方法:
进入到BeanFactory接口的getBean方法。该方法由它的实现类AbstractBeanFactory进行实现。AbstractBeanFactory类继承结构如下图:
接下来我们进入到AbstractBeanFactory的getBean(String beanName)方法:
接下来要进入正文了。
点击进入doGetBean(name, null, null, false)方法,首先第一行就是
该方法就是(1)转换对应的beanName.我们传入的name可能是别名,也可能是FactoryBean,所以需要进行一系列的解析。比如取指定的别名alias所表示的最终beanName,或者当传入的name="&car"时,会先去除&,而使得name="car"。
接下来就是(2)尝试从缓存中加载单例:
进入getSingleton方法:
单例在spring的同一个容易内只会被创建一次,后续再获取bean就直接从单例缓存中获取。其中的singletonFactorys用来存储beanName和创建bean的工厂之间的关系,也就是beanName-->ObjectFactory。在第一次创建原始bean时会添加相应的beanNme-->ObjectFactory关系。然后在循环依赖调用getSingleton(beanName)方法时可以通过获取相应的bean工厂,然后通过objectFactory获取bean,从而解决单例模式的循环依赖问题。
接下来进行(3)原型模式的依赖检查:
目前spring只对单例模式通过setter方式注入构成的循环依赖进行了处理。因为spring容器不进行缓存"prototype"作用域的bean,因此无法提前暴露一个创建中的bean,所以原型模式的循环依赖无法处理,直接报异常。
接下来进行(4)parentFactory的检测。这个没什么可说的,如果parentFactory不为空并且当前加载xml文件所对应的Definition不存在,就只能通过parentFactory调用getBean方法获取bean了。
接下来就是将(5)存储配置文件的GernericDefinition转换成RootDefinition,因为bean所有的后续的处理都是针对于RootDefinition的。如果bean的父类不为空,则会合并父类的属性。
因为在bean的初始过程中可能会用到其他的属性,并且可能是动态配置的,并且配置成依赖于其他的bean,所以在初始化一个bean时首先会(6)初始化这个bean所对应的依赖。
这里对bean相关的依赖就行了注册,当这个bean被销毁之前会对相关注册的依赖缓存进行删除。并且初始化依赖的ben。
接下来就进入到了(7)根据不同scope进行bean的创建环节。这里主要分成了单例、原型和其他三种情况。因为我们在开发过程中主要用到的是单例,所以接下来只看单例模式好了。
这里的getSingleton方法是getSingleton(String beanName, ObjectFactory> singletonFactory)。是最开始的那个getSingleton方法的重载方法。这个方法的中beforeSingletonCreation(String beanName)中进行了this.singletonsCurrentlyInCreation.add(beanName)处理。也就使得最开始获取单例缓存时的条件判断isSingletonCurrentlyInCreation(beanName)为true。
我们进入createBean方法,然后直接跳转到AbstractAutowireCapableBeanFactory类的doCreateBean方法。这里面主要进行了如下处理:
1.实例化bean。主要获取通过BeanWrapper获取包装bean实例。
2.允许post-processors修改合并的bean Definition。
3.添加bean-->ObjectFactory关系缓存。
4.初始化bean。
包括对bean的属性注入以及对bean实现了相关Aware类以及初始化前,初始化时,初始化后的相关处理。
属性注入主要包括根据type进行注入和根据name进行注入。
初始化主要包括了如下的工作:
比如:
当bean实现了BeanNameAware时,则调用BeanNameAware的setBeanName方法;
当bean实现了BeanClassLoaderAware时,则调用BeanClassLoaderAware的setBeanClassLoader方法;
当bean实现了BeanFactoryAware时,则调用BeanFactoryAware的setBeanFactory方法;
当bean实现了BeanPostProcessor时,调用BeanPostProcessor的postProcessBeforeInitialization方法;当bean实现了initializingBean,则调用initializingBean的afterPropertiesSet方法,假如自定义了init-method,则调用自定义的初始化方法;
当bean实现了BeanPostProcessor时,则调用BeanPostProcessor的postProcessAfterInitialization方法;
5.当bean配置了destroy bean的相关方法时,对该方法进行注册。
最后,有可能返回的bean的类型跟要求的类型不一致,那么就需要进行(8)类型转换了。
以上就是所有的bean的加载过程,这个时候就可以返回我们需要的bean了。