以FileSystemXmlApplicationContext.java为例加载xml文件
1、FileSystemXmlApplicationContext.java类的refresh()方法为入口,因为此方法为此类的构造器调用
2、进入AbstractApplicationContext.java类的refresh()方法,主要调用ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
3、进入AbstractApplicationContext.java类的obtainFreshBeanFactory()方法,主要调用refreshBeanFactory();
4、进入AbstractRefreshableApplicationContext.java类的refreshBeanFactory(),接着调用loadBeanDefinitions(beanFactory); 此beanFactory为DefaultListableBeanFactory。
5、回调AbstractRefreshableApplicationContext类的子类的AbstractXmlApplicationContext.java的loadBeanDefinitions(DefaultListableBeanFactory beanFactory)方法,接着调用loadBeanDefinitions(beanDefinitionReader);
6、进入AbstractXmlApplicationContext.java类的loadBeanDefinitions(XmlBeanDefinitionReader reader),接着调用reader.loadBeanDefinitions(configLocations);
7、进入AbstractBeanDefinitionReader.java类的loadBeanDefinitions(String... locations)方法,调用counter += loadBeanDefinitions(location);
8、进入AbstractBeanDefinitionReader.java类的loadBeanDefinitions(String location, Set
resourceLoader.getResource(location)调用DefaultResourceLoader.java类的public Resource getResource(String location) 方法,会进入异常调用return getResourceByPath(location); 此句回调FileSystemXmlApplicationContext.java类的protected Resource getResourceByPath(String path) 方法。返回FileSystemResource的对象。
9、回到AbstractBeanDefinitionReader.java类的loadBeanDefinitions(String location, Set
10、进入XmlBeanDefinitionReader.java类的loadBeanDefinitions(EncodedResource encodedResource)方法,进入到InputStream inputStream = encodedResource.getResource().getInputStream();此行, 此行调用FileSystemResource.java类的getInputStream()方法,因为第8步最后返回的是FileSystemResource的对象。这样就得到了文件的inputStream。
以上10步完成了resource的定位
2、调用XmlBeanDefinitionReader.java类的
通过查看Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());的源码可以知道spring加载xml文件是采用dom方式,将文件流一次性加载到内存中,这样解析是最快的,
3、进入XmlBeanDefinitionReader.java类的registerBeanDefinitions(Document doc, Resource resource)方法,
主要分析documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
4、进入DefaultBeanDefinitionDocumentReader.java类的
5、进入DefaultBeanDefinitionDocumentReader.java类的
6、进入DefaultBeanDefinitionDocumentReader.java类的
7、进入DefaultBeanDefinitionDocumentReader.java类的
先分析红色圈1标记:这个非常重要,是解析xml文件的配置的所有bean以及各种bean的属性的方法,先看BeanDefinitionHolder,是包含BeanDefinition的组合类。
进入BeanDefinitionParserDelegate.java类的parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)方法。主要查看
进入public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) 方法,主要查看
以上一系列方法是将解析出来的xml里节点的属性的值赋给AbstractBeanDefinition对象的属性。最后调用return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 将AbstractBeanDefinition对象复制给 BeanDefinitionHolder对象。此代码在BeanDefinitionParserDelegate.java类的parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)方法最后面。
经过上面的多个方法后,xml里节点的各属性值已经解析到BeanDefinitionHolder类的对象了。
以上各步完成了BeanDefinition的载入。
下面进入第7步截图的圆圈2标记。
1、进入BeanDefinitionReaderUtils.java类的registerBeanDefinition()方法。
2、进入DefaultListableBeanFactory.java类的registerBeanDefinition()方法。
此方法为将xml的每一个bean(按id区分,方法中的beanName为每个bean的Id)加入到beanDefinitionMap中,beanName为map的key,beanDefinition为map的value。加入前先判断是不是已经存在,然后根据allowBeanDefinitionOverriding的值来判断是否抛出异常。如果不抛出异常,则替换!
这样整个IOC的初始化工作就做完了!