1. 初始化
大致单步跟了下Spring IOC的初始化过程,整个脉络很庞大,初始化的过程主要就是读取XML资源,并解析,最终注册到Bean Factory中:
在完成初始化的过程后,Bean们就在BeanFactory中蓄势以待地等调用了。下面通过一个具体的例子,来详细地学习一下初始化过程,例如当加载下面一个bean:
1 | <bean id="XiaoWang" class="com.springstudy.talentshow.SuperInstrumentalist"> |
加载时需要读取、解析、注册bean,这个过程具体的调用栈如下所示:
下面对每一步的关键的代码进行详细分析:
1.1 准备
保存配置位置,并刷新
在调用ClassPathXmlApplicationContext后,先会将配置位置信息保存到configLocations,供后面解析使用,之后,会调用AbstractApplicationContext
的refresh方法进行刷新:
1 | public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, |
创建载入BeanFactory
1 | protected final void refreshBeanFactory() throws BeansException { |
创建XMLBeanDefinitionReader
1 | protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) |
1.2 读取
创建处理每一个resource
1 | public int loadBeanDefinitions(String location, Set<Resource> actualResources) |
处理XML每个元素
1 | protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { |
解析和注册bean
1 | protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { |
本步骤中,通过parseBeanDefinitionElement
将XML的元素解析为BeanDefinition
,然后存在BeanDefinitionHolder
中,然后再利用BeanDefinitionHolder
将BeanDefinition
注册,实质就是把BeanDefinition
的实例put进BeanFactory
中,和后面将详细的介绍解析和注册过程。
1.3 解析
处理每个Bean的元素
1 | public AbstractBeanDefinition parseBeanDefinitionElement( |
处理属性的值
1 | public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) { |
1.4 注册
1 | public static void registerBeanDefinition( |
注册过程中,最核心的一句就是:this.beanDefinitionMap.put(beanName, beanDefinition)
,也就是说注册的实质就是以beanName为key,以beanDefinition为value,将其put到HashMap中。
2. 注入依赖
当完成初始化IOC容器后,如果bean没有设置lazy-init(延迟加载)属性,那么bean的实例就会在初始化IOC完成之后,及时地进行初始化。初始化时会先建立实例,然后根据配置利用反射对实例进行进一步操作,具体流程如下所示:
创建bean的实例
创建bean的实例过程函数调用栈如下所示:
注入bean的属性
注入bean的属性过程函数调用栈如下所示:
在创建bean和注入bean的属性时,都是在doCreateBean函数中进行的,我们重点看下:
1 | protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, |
理解了以上两个过程,我们就可以自己实现一个简单的Spring框架了。于是,我根据自己的理解实现了一个简单的IOC框架Simple Spring,有兴趣可以看看。