1.编程方式使用IOC容器的步骤为
1:定位文件得到resource(注释1):ClassPathResource classPathResource=new ClassPathResource("spring.xml");
2:创建容器 DefaultListableBeanFactory defaultListableBeanFactory=new DefaultListableBeanFactory();
3:创建beandefinitionReader(注释2),XmlBeanDefinitionReader XmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
4:使用reader进行载入注册,完成容器的装配
容器的初始化过程也与上述情况相似,以FileSystemXmlApplicationContext为例.
容器的初始化起源于refresh方法(ConfigurableApplicationContext规定实现,即说明:如果自定义容器想要能启动,必须继承该接口或者webapplicationContext),
接着执行容器的获取,正在的容器获取是由AbstractRefreshableApplicationContext完成,其中创建了DefaultListableBeanFactory,并开始loadBeanDefinitions(beanFactory);,这一过程包含了文件的定位,解析载入和注册。具体实现在AbstractXmlApplicationContext,代码如下
其中要注意的是,XmlBeanDefinitionReader对象在创建的时候就已经由父类构造器默认分配了一个DefaultResourceLoader,父类构造器代码如下
这里又setClassLoader(this),自身就是一个DefaultClassLoader(你也可以自定义ClassLoader,spring并没有将其写死),接下来解析location
PS,这里有一个疑问,前面说过传入的resourceLoader是DefaultResourceLoader,但是同时也实现了ResourcePatternResolver接口
具体获得resource的过程如下
这里我们就明白了,getResourceByPath不是defaultResourceLoader中的了,而是在FileSystemXmlApplicationContext中了的。到此我们已经定位得到了resource。
我们可以看到获得resource之后马上就对resource进行了解析,而这个解析过程是由xmlBeanDefinitionReader委托给documentReader来完成的,代码如下
documentReader为DefaultBeanDefinitionDocumentReader,doc为org.w3c.dom.Document,具体解析document跟一般情况一样。
产生beandefinitionHolder(其拥有beandefinition,和它的名字别名。),并将其注册到一个ioc容器中
产生beandefinitionHolder的过程
生成beanDefinition,并反射出类对象储存到beanDefinition中。
注册过程如下,建立一个映射关系的CurrentHashmap
注释1:resource的继承关系图如下,根据不同类型定位得到不同的resource。
注释2,虽然XML形式的文件是主流,但是spring依然为其准备了其他形式的reader,如下图