1.XmlBeanFactory加载过程(IoC的初始化)
根据书中所描述的,IoC容器大体应该是由三部分组成,分别是resource,factory和reader。
编程式使用IoC容器:
ClassPathResource res = new ClassPathResource("beans.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); reader.loadBeanDefinitions(res);
首先通过外部的xml文件创建所需要的资源(resource)
再定义使用的工厂,这里使用的是DefaultListableBeanFactory
在定义使用的读取器,XmlBeanDefinitionReader
最后将资源装入读取器中建立起IoC容器
只是通过这几行代码和书中的简单介绍自己理解了一下,可能在理解上有些错误,根据后面的学习将进一步理解IoC容器的加载。
2.ApplicationContext和BeanFactory的区别
1)支持不同的信息源。信息源的扩展功能可以实现国际化,为开发多语言版本的应用提供服务。
2)访问资源。可以通过各种各样的方式访问到资源。
3)支持应用事件。在上下文中引入和事件机制。可以理解为监控Bean的生命周期,并在周期的各个时间点进行管理。
4)在ApplicationContext中提供的附加服务。扩展框架,提供丰富的功能。
3.ApplicationContext,IoC容器的初始化过程(以FileSystemXmlApplicationContext为例)
构造函数:
public FileSystemXmlApplicationContext(String[] configLocation, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocation(configLocations); if (refresh) { refresh(); } }
protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); }
上面的代码是获取资源定位。
IoC容器的初始化是通过refresh()方法启动的,这个启动的过程包括三项:BeanDefinition的Resource定位,载入和注册。
1)定位:由ResourceLoader通过统一的Resource接口来完成。一看到Loader就感觉是加载器了,这里明显加载的是文件系统的资源或者是类路径中的资源等等。
2)载入:比如用户将Bean定义在xml文件中,但是真正的IoC容器是不会识别xml的,所以通过加载将定义好的Bean解释为IoC容器的内部数据结构。重点就在这里,所谓的内部数据结构就是BeanDefinition了,实际上就是一堆POJO对象在IoC容器中的抽象。
3)注册:这个过程通过BeanDefinitionRegistry完成(名字一目了然)。最终是通过一个HashMap来持有这些BeanDefinition数据的。
4.BeanDefinition的Resource定位
所谓的定位其实就是找到本地的文件进行加载。定位出来的东西叫做Resource,是个对象。这个Resource对象不能直接被BeanFactory直接使用,而是要通过一个叫做BeanDefinitionReader的类进行处理,解析完成后的东西才能被BeanFactory使用(貌似是这个意思)。简单的说就是:对于BeanFactory,IoC容器和资源读取器是解耦的,如果想要使用IoC容器,并且使用本地配置好Bean信息的文件,则需要为IoC容器配置一个特定的读取器才行。好不容易才用自己的话理解了。。。
再来说ApplicationContext,他们从名字上就可以看出来提供了哪些不同的Resource读入功能,FileSystem开头的表示从文件系统中载入等等。。也就是说ApplicationContext已经为我们提供了读取器,不需要再额外设置了,可能灵活性差一点,不过封装了的东西用起来肯定舒服(个人感觉,更无脑一点)。
FileSystemXmlApplicationContext中的refresh()方法调用了AbstractRefreshableApplicationContext中的refreshBeanFactory()方法,此方法中主要方法是createBeanFactory()和loadBeanDefinition(),前者创建了IoC容器(这里是DefaultListableBeanFactory),后者用来获取所需要的资源,完成了BeanDefinition的定位。
因此就可以将BeanDefinition中的信息载入到IoC容器中并注册了。