ApplicationContext是对BeanFactory的一个扩展,观察ApplicationContext接口我们可以发现,这个接口除了继承了ListableBeanFactory和HierarchicalBeanFactory(BeanFactory的子接口)外,还继承了ApplicationEventPublisher和MessageSource接口,这两个接口就为ApplicationContext提供了容器内事件发布和国际化的信息支持等新功能。
关于BeanFactory还有很多要说的东东,包括XML中的元素,注解注入,生命周期等等,这些东西会在Spring实战篇和以后逐渐说明。
在BeanFactory中我们用到了Resource类去加载资源文件,Resource有以下五个实现类:
ByteArrayResource
ClassPathResource
FileSystemResource
UrlResource
通过名字就能看出它们的作用,这里也就不多说了。
Resource有一个子接口叫做ResourceLoader,这个接口主要通过getResource(String)方法定位和查找资源,其实现类有以下两个:
DefaultResourceLoader:首先尝试以classpath:前缀打头;若没有尝试URL定位;还是没有最后会委派给getResourceByPath(String) 方法来定位,构造ClassPathResource类型的资源并返回。
FileSystemResourceLoader:继承自DefaultResourceLoader,覆写了getResourceByPath(String)方法,使之从文件系统加载资源并以FileSystemResource类型返回。
当然,不得不提一下ResourcePatternResolver,它是ResourceLoader的子接口,并且定义了Resource[] getResources(String)方法用来批量查找资源。看这个接口的名字就知道它与正则表达式有关,其最常用的实现类为PathMatchingResourcePatternResolver。
说了这么多关于资源加载、定位和查找的东东,那这和ApplicationContext有什么关系呢?在使用BeanFactory的时候我们知道,必须要通过Resource类加载资源。而ApplicationContext是一个接口,其实现类都会直接或间接地继承AbstractApplicationContext这个类,而这个类就继承了DefaultResourceLoader这个ResourceLoader的实现类。也就是说ApplicationContext可以直接自己去定位和查找资源,而不用像BeanFactory那样通过组合实现,代码上更简洁了一些。
那ResourcePatternResolver呢,ApplicationContext当然不会放弃这么有用的接口,在AbstractApplicationContext内部声明了一个ResourcePatternResolver的成员,实现就是上面说的PathMatchingResourcePatternResolver。而PathMatchingResourcePatternResolver在构造的时候需要一个ResourceLoader参数,好吧,这时候直接把AbstractApplicationContext自己(this)传入就万事OK了。
下面说下ApplicationContext的实现类,很简单,最常用的就是ClassPathXmlApplicationContext(classpath:前缀)和FileSystemXmlApplicationContext。功能嘛,通过名字一目了然,构参都是一个String类型的路径,没什么好说的。
现在,你可以使用ApplicationContext去改写那些使用BeanFactory的应用了,毕竟BeanFactory已经不推荐使用了,而且ApplicationContext更加简洁实用,功能也更多。
在我们学习和使用Spring的时候,我们经常会看到一些以Aware结尾的接口,比如ResourceLoaderAware和ApplicationContextAware。去看源码(好吧,这个我经常会说到,也是学习语言或框架必须的过程),我们可以看到这些接口都继承自一个空接口Aware,其内部也只有一个setXXX的方法。这些接口的作用简单来说就是在这些Bean初始化之后,Spring按照实现的接口自动注入相应的资源,这样这个Bean就可以拥有一些资源的功能。
<!--EndFragment-->