一堆图预警~~~
通过测试启动类进入ApplicationContext容器 设置(解析)配置文件路径setConfigLocations(configLocations);
-
参数configLocations格式是String[]
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2.创建工厂:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
先创建一个工厂,创建的工厂的名字是 DefaultListableBeanFactory
refreshBeanFactory()
自定义风格化的customizeBeanFactory(beanFactory);
这两个属性默认都是true(父类构造时赋的值)
超级重要的loadBeanDefinitions(beanFactory)
点进方法看到啥都木有,同学不要慌~~点下面就可以看到他的实现子类啦。。。
由上图可以发现,在Spring中这个方法有四个实现,选择进入哪个取决于你使用的配置方式:
-
AbstractXmlApplicationContext (org.springframework.context.support)
-
使用的是xml配置bean的选这个
-
位于spring.spring-context.main
-
-
AnnotationConfigWebApplicationContext (org.springframework.web.context.support)
-
spring.spring-web.main
-
-
GroovyWebApplicationContext (org.springframework.web.context.support)
-
spring.spring-web.main
-
-
XmlWebApplicationContext (org.springframework.web.context.support)
-
spring.spring-web main
-
由于本文是以xml配置文件为示例,故我们选择AbstractXmlApplicationContext这个类里的
loadBeanDefinitions(beanDefinitionReader)的实现
再次进入名为loadBeanDefinitions(beanDefinitionReader) 的方法中
再再次进入名为loadBeanDefinitions(configLocations) 的方法中
再再再次进入名为loadBeanDefinitions(location)的方法中
再再再再次进入名为loadBeanDefinitions(resources) 的方法中
再再再再再次进入名为loadBeanDefinitions(resources) 的方法中
进入其实现子类
选择类XmlBeanDefinitionReader
再再再再再再次进入名为loadBeanDefinitions(resources) 的方法中
doLoadBeanDefinitions(inputSource, encodedResource.getResource());
再次进入名为doLoadBeanDefinitions(inputSource, encodedResource.getResource())的方法中
doLoadDocument(InputSource inputSource, Resource resource)
getValidationModeForResource(Resource resourc)
detectValidationMode(Resource resource)
detectValidationMode(InputStream inputStream)
loadDocument()
先总结下配置参数configLocations的类型转换的过程:
String[] ---> String ---> Resource[] ---> Resource ---> document文档 ---> 根据文档的节点信息封装成一个个的BeanDefinition
继续!~
registerBeanDefinitions(doc, resource);
createBeanDefinitionDocumentReader()
registerBeanDefinitions(doc, createReaderContext(resource));
doRegisterBeanDefinitions(Element root) ;
我们转换的是BeanDefinition,所以进入了BEAN_ELEMENT这个条件分支中
选择子类DefaultListableBeanFactory
下面两张图是一个函数(这个函数有点长~)
走到这里,我们见证了BeanDefinition和BeanName都被放进了相应的容器内!
this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName);
这篇就先到这了喽~下篇继续 >>> 努力脸.gif



