1 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml"); |
spring的bean加载是从getBean方法开始的。
一、从缓存中获取bean
1 | Object sharedInstance = getSingleton(beanName); |
该方法首先尝试从singletonObjects里面获取实例,如果获取不到再从earlySingletonObjects里获取,如果还获取不到,再尝试从sigletonFactories里面获取beanName对应的ObjectFactory,然后调用这个ObjectFactory的getObject来创建bean,并放到earlySingletonObjects,并将sigletonFactories的对应bean缓存删除掉。
存储bean的map解释:
1 | /** Cache of singleton objects: bean name to bean instance. */ |
singletonObjects 用于保存BeanName和创建bean实例之间的关系。
1 | /** Cache of early singleton objects: bean name to bean instance. */ |
earlySingletonObjects 提前曝光的单例对象缓存,用于解决循环依赖
1 | /** Cache of singleton factories: bean name to ObjectFactory. */ |
singletonFactories 用于保存BeanName和创建bean的工厂之间的关系。
内部方法解释:
1 | public boolean isSingletonCurrentlyInCreation(String beanName); |
判断当前bean是否处于创建中,即正在初始化,但是尚未完成初始化。
allowEarlyReference参数:是否允许从singletonFactories缓存中通过getObject方法拿到bean对象。
二、从bean实例中获取对象
1 | beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); |
在getBean
方法中获取到的bean,只是原始状态的bean,不一定是我们想要的。需要调用getObjectForBeanInstance
进行处理。getObjectForBeanInstance
对非factoryBean不做处理,直接返回,将解析bean的工作委托给getObjectFromFactoryBean
。
1 | if (factory.isSingleton() && containsSingleton(beanName)) |
getObjectFromFactoryBean
方法主要内容是如果是单例则从缓存中获取,缓存没有则从factoryBean中获取。如果不是单例,则直接去从factoryBean中获取bean.获取bean的操作又委托给了doGetObjectFromFactoryBean
,最终调用 object = factory.getObject();
获取bean.
三、获取bean流程
从spring容器中获取单例时有两种情况:缓存中存在和缓存中不存在。在上面缓存中不存在单例bean时,是通过getSingleton的重载方法来实现bean的加载的。
1 | sharedInstance = getSingleton(beanName, () -> { |
主要过程为:
1,再次尝试从缓存中取出bean
1 | Object singletonObject = this.singletonObjects.get(beanName); |
2, 若没有加载,则记录beanName的正在加载状态
1 | beforeSingletonCreation(beanName); |
3, 通过传入ObjectFactory创建bean
1 | singletonObject = singletonFactory.getObject(); |
4,当bean加载结束后需要移除缓存中正在加载状态
1 | protected void afterSingletonCreation(String beanName) { |
5,将结果记录至缓存并删除加载bean所记录的各种辅助状态
1 | addSingleton(beanName, singletonObject); |
四、创建bean
return createBean(beanName, mbd, args);
太长,另起一篇。