在使用经典(非web)模式的spring时,我们往往从一个applicationContext的实例来作为整个spring应用的入口,applicationContext作为应用上下文,既承担着加载配置文件的责任,又必须对外提供接口访问内部ioc容器中的对象。因此我们从applicationContext开始理清它的继承线,它的整个继承图如下:
整个继承图中我们只需要关注两个比较重要的继承线:
1.BeanFactory到ApplicationContext的继承线;
2.ResourceLoader到ApplicationContext的继承线
其他的一些继承关系,比如ApplicationEventPublisher用来发布应用事件给监听者,MessageSource用来支持国际化不是重点。
BeanFactory有什么作用呢?根据上文,applicationContext必须对外提供接口访问内部ioc容器中的对象,其实这些接口正是继承自BeanFactory及它的子接口的。完整的接口定义如下:
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
BeanFactory有几个重要的子接口(类),这些接口在原有的接口上进行了进一步的接口扩展。如ListableBeanFactory主要添加了支持枚举ioc容器中的bean和bean定义的接口。比如,返回某些具备同样特征的bean(bean定义)的列表(具体可以看ListableBeanFactory接口说明);HierarchicalBeanFactory则主要添加了分层的beanFactory支持,这也意味着分层的ioc容器。
接下来在看看ResourceLoader,该接口主要用来根据location获取资源(Resource),如:
public interface ResourceLoader {
String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;
Resource getResource(String location);
@Nullable
ClassLoader getClassLoader();
}
ResourceLoader的继承线如下:承线如下:ResourceLoader的继承线如下:ResourceLoader的继承线如下:ResourceLoader的继承线如下:ResourceLoader:资源加载顶级接口
ResourceLoader:(I)资源加载顶级接口
----------
ResourcePatternResolver:(I)支持根据占位符正则匹配返回多个资源
----------------- PathMatchingResourcePatternResolver:(C)具体实现类
现在我们再来看ApplicationContext接口,通过继承了这两个主要的接口,它同时具备了加载资源和访问ioc容器中的对象的功能。
了解了这些基本的接口概念,我们来看下ClassPathXmlApplicationContext的具体继承关系图和具体实现:
ApplicationContext:应用上下文顶级接口,无法更改配置
ConfigurableApplicationContext:在ApplicationContext基础上继承了Lifecycle接口,支持配置应用上下文,支持生命周期控制
AbstractApplicationContext:ApplicationContext的抽象类实现,简单的实现了一些功能方法和通用骨架,使用模版方法模式,具体实现在子类中
AbstractRefreshableApplicationContext: 支持更新操作的抽象类(refresh操作AbstractApplicationContext只给出了基本骨架)
AbstractRefreshableConfigApplicationContext:可配置的AbstractRefreshableApplicationContext
AbstractXmlApplicationContext:对象配置资源文件放在xml中,通过
XmlBeanDefinitionReader读取配置
ClassPathXmlApplicationContext:实现了getConfigResources方法的具体类
从继承线中可以看到,spring将只读接口和可配置接口进行了分层。(这样分层的具体优点?)
仔细看这些继承类的代码,我们会发现,虽然ApplicationContext实现了以下四大功能:
1.访问(注册)应用中的组件(继承自
ListableBeanFactory)
2.以一种的方式加载文件资源(继承自
ResourceLoader)
3.向所有注册的监听器发布事件(继承自
ApplicationEventPublisher)
4.解析信息,支持国际化(继承自
MessageSource)
但这些具体的逻辑实现并不是由ApplicationContext的实现类来具体实现,而是委托给ApplicationContext实现类内部的这些接口的实现对象来进行处理,ApplicationContext只提供一个外层的接口。比如BeanFactory的相关接口就是将请求转发给AbstractRefreshableApplicationContext中的DefaultListableBeanFactory类型的BeanFactory来具体实现的。这样的好处就是将接口的调用和实现隔离开。
既然和ioc相关的操作都会直接转发给DefaultListableBeanFactory类型的对象,那我们就必须了解DefaultListableBeanFactory的继承线:
这里有三条比较重要的继承线:
其中一条是关于注册单例对象/bean定义接口作为顶级接口的继承线,如红线所示,主要就是给该类添加注册对象到该应用的ioc容器中的接口。
还有一条是用于在BeanFactory的基础上提供自动装配的功能的继承线,如黑线所示
最后一条是常规的关于BeanFactory和它的一些扩展接口的继承线
其中关于bean定义的对象的kv对保存在DefaultListableBeanFactory中,单例对象的kv对保存在DefaultSingletonBeanRegistry中。