Spring IOC核心源码学习

转自:Yikun-Spring IOC核心源码学习

1. 初始化


大致单步跟了下Spring IOC的初始化过程,整个脉络很庞大,初始化的过程主要就是读取XML资源,并解析,最终注册到Bean Factory中:

在完成初始化的过程后,Bean们就在BeanFactory中蓄势以待地等调用了。下面通过一个具体的例子,来详细地学习一下初始化过程,例如当加载下面一个bean:


 
 
  1. <bean id= "XiaoWang" class= "com.springstudy.talentshow.SuperInstrumentalist">
  2. <property name= "instruments">
  3. <list>
  4. <ref bean= "piano"/>
  5. <ref bean= "saxophone"/>
  6. </list>
  7. </property>
  8. </bean>


加载时需要读取、解析、注册bean,这个过程具体的调用栈如下所示:

下面对每一步的关键的代码进行详细分析:
1.1 准备

保存配置位置,并刷新
在调用ClassPathXmlApplicationContext后,先会将配置位置信息保存到configLocations,供后面解析使用,之后,会调用AbstractApplicationContext的refresh方法进行刷新:

 
 
  1. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh,
  2. ApplicationContext parent) throws BeansException {
  3. super(parent);
  4. // 保存位置信息,比如`com/springstudy/talentshow/talent-show.xml`
  5. setConfigLocations(configLocations);
  6. if (refresh) {
  7. // 刷新
  8. refresh();
  9. }
  10. }
  11. public void refresh() throws BeansException, IllegalStateException {
  12. synchronized ( this.startupShutdownMonitor) {
  13. // Prepare this context for refreshing.
  14. prepareRefresh();
  15. // Tell the subclass to refresh the internal bean factory.
  16. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  17. // Prepare the bean factory for use in this context.
  18. prepareBeanFactory(beanFactory);
  19. try {
  20. // Allows post-processing of the bean factory in context subclasses.
  21. postProcessBeanFactory(beanFactory);
  22. // Invoke factory processors registered as beans in the context.
  23. invokeBeanFactoryPostProcessors(beanFactory);
  24. // Register bean processors that intercept bean creation.
  25. registerBeanPostProcessors(beanFactory);
  26. // Initialize message source for this context.
  27. initMessageSource();
  28. // Initialize event multicaster for this context.
  29. initApplicationEventMulticaster();
  30. // Initialize other special beans in specific context subclasses.
  31. onRefresh();
  32. // Check for listener beans and register them.
  33. registerListeners();
  34. // Instantiate all remaining (non-lazy-init) singletons.
  35. finishBeanFactoryInitialization(beanFactory);
  36. // Last step: publish corresponding event.
  37. finishRefresh();
  38. }
  39. catch (BeansException ex) {
  40. // Destroy already created singletons to avoid dangling resources.
  41. destroyBeans();
  42. // Reset 'active' flag.
  43. cancelRefresh(ex);
  44. // Propagate exception to caller.
  45. throw ex;
  46. }
  47. }
  48. }


创建载入BeanFactory


 
 
  1. protected final void refreshBeanFactory() throws BeansException {
  2. // ... ...
  3. DefaultListableBeanFactory beanFactory = createBeanFactory();
  4. // ... ...
  5. loadBeanDefinitions(beanFactory);
  6. // ... ...
  7. }



创建XMLBeanDefinitionReader

 
 
  1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
  2. throws BeansException, IOException {
  3. // Create a new XmlBeanDefinitionReader for the given BeanFactory.
  4. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
  5. // ... ...
  6. // Allow a subclass to provide custom initialization of the reader,
  7. // then proceed with actually loading the bean definitions.
  8. initBeanDefinitionReader(beanDefinitionReader);
  9. loadBeanDefinitions(beanDefinitionReader);
  10. }


1.2 读取

创建处理每一个resource


 
 
  1. public int loadBeanDefinitions(String location, Set<Resource> actualResources)
  2. throws BeanDefinitionStoreException {
  3. // ... ...
  4. // 通过Location来读取Resource
  5. Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
  6. int loadCount = loadBeanDefinitions(resources);
  7. // ... ...
  8. }
  9. public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
  10. Assert.notNull(resources, "Resource array must not be null");
  11. int counter = 0;
  12. for (Resource resource : resources) {
  13. // 载入每一个resource
  14. counter += loadBeanDefinitions(resource);
  15. }
  16. return counter;
  17. }


处理XML每个元素

 
 
  1. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
  2. // ... ...
  3. NodeList nl = root.getChildNodes();
  4. for ( int i = 0; i < nl.getLength(); i++) {
  5. Node node = nl.item(i);
  6. if (node instanceof Element) {
  7. Element ele = (Element) node;
  8. if (delegate.isDefaultNamespace(ele)) {
  9. // 处理每个xml中的元素,可能是import、alias、bean
  10. parseDefaultElement(ele, delegate);
  11. }
  12. else {
  13. delegate.parseCustomElement(ele);
  14. }
  15. }
  16. }
  17. // ... ...
  18. }


解析和注册bean

 
 
  1. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
  2. // 解析
  3. BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
  4. if (bdHolder != null) {
  5. bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
  6. try {
  7. // 注册
  8. // Register the final decorated instance.
  9. BeanDefinitionReaderUtils.registerBeanDefinition(
  10. bdHolder, getReaderContext().getRegistry());
  11. }
  12. catch (BeanDefinitionStoreException ex) {
  13. getReaderContext().error( "Failed to register bean definition with name '" +
  14. bdHolder.getBeanName() + "'", ele, ex);
  15. }
  16. // Send registration event.
  17. getReaderContext().fireComponentRegistered( new BeanComponentDefinition(bdHolder));
  18. }
  19. }


本步骤中,通过parseBeanDefinitionElement将XML的元素解析为BeanDefinition,然后存在BeanDefinitionHolder中,然后再利用BeanDefinitionHolder将BeanDefinition注册,实质就是把BeanDefinition的实例put进BeanFactory中,和后面将详细的介绍解析和注册过程。
1.3 解析

处理每个Bean的元素

 
 
  1. public AbstractBeanDefinition parseBeanDefinitionElement(
  2. Element ele, String beanName, BeanDefinition containingBean) {
  3. // ... ...
  4. // 创建beandefinition
  5. AbstractBeanDefinition bd = createBeanDefinition(className, parent);
  6. parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
  7. bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
  8. parseMetaElements(ele, bd);
  9. parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
  10. parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
  11. // 处理“Constructor”
  12. parseConstructorArgElements(ele, bd);
  13. // 处理“Preperty”
  14. parsePropertyElements(ele, bd);
  15. parseQualifierElements(ele, bd);
  16. // ... ...
  17. }


处理属性的值

 
 
  1. public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
  2. String elementName = (propertyName != null) ?
  3. "<property> element for property '" + propertyName + "'" :
  4. "<constructor-arg> element";
  5. // ... ...
  6. if (hasRefAttribute) {
  7. // 处理引用
  8. String refName = ele.getAttribute(REF_ATTRIBUTE);
  9. if (!StringUtils.hasText(refName)) {
  10. error(elementName + " contains empty 'ref' attribute", ele);
  11. }
  12. RuntimeBeanReference ref = new RuntimeBeanReference(refName);
  13. ref.setSource(extractSource(ele));
  14. return ref;
  15. }
  16. else if (hasValueAttribute) {
  17. // 处理值
  18. TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
  19. valueHolder.setSource(extractSource(ele));
  20. return valueHolder;
  21. }
  22. else if (subElement != null) {
  23. // 处理子类型(比如list、map等)
  24. return parsePropertySubElement(subElement, bd);
  25. }
  26. // ... ...
  27. }


1.4 注册

 
 
  1. public static void registerBeanDefinition(
  2. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  3. throws BeanDefinitionStoreException {
  4. // Register bean definition under primary name.
  5. String beanName = definitionHolder.getBeanName();
  6. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  7. // Register aliases for bean name, if any.
  8. String[] aliases = definitionHolder.getAliases();
  9. if (aliases != null) {
  10. for (String alias : aliases) {
  11. registry.registerAlias(beanName, alias);
  12. }
  13. }
  14. }
  15. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
  16. throws BeanDefinitionStoreException {
  17. // ......
  18. // 将beanDefinition注册
  19. this.beanDefinitionMap.put(beanName, beanDefinition);
  20. // ......
  21. }


注册过程中,最核心的一句就是: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,
  2. final Object[] args) {
  3. // Instantiate the bean.
  4. BeanWrapper instanceWrapper = null;
  5. if (mbd.isSingleton()) {
  6. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  7. }
  8. if (instanceWrapper == null) {
  9. // 创建bean的实例
  10. instanceWrapper = createBeanInstance(beanName, mbd, args);
  11. }
  12. // ... ...
  13. // Initialize the bean instance.
  14. Object exposedObject = bean;
  15. try {
  16. // 初始化bean的实例,如注入属性
  17. populateBean(beanName, mbd, instanceWrapper);
  18. if (exposedObject != null) {
  19. exposedObject = initializeBean(beanName, exposedObject, mbd);
  20. }
  21. }
  22. // ... ...
  23. }


理解了以上两个过程,我们就可以自己实现一个简单的Spring框架了。于是,我根据自己的理解实现了一个简单的IOC框架Simple Spring,有兴趣可以看看。

转自:http://yikun.github.io/2015/05/29/Spring-IOC%E6%A0%B8%E5%BF%83%E6%BA%90%E7%A0%81%E5%AD%A6%E4%B9%A0/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值