在使用经典(非web)模式的spring时,我们往往从一个applicationContext的实例来作为整个spring应用的入口,applicationContext作为应用上下文,既承担着加载配置文件的责任,又必须对外提供接口访问内部ioc容器中的对象。因此我们从applicationContext开始理清它的继承线,它的整个继承图如下:

不继承springboot父项目_不继承springboot父项目

整个继承图中我们只需要关注两个比较重要的继承线:

     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的具体继承关系图和具体实现:

不继承springboot父项目_加载_02

ApplicationContext:应用上下文顶级接口,无法更改配置

     ConfigurableApplicationContext:在ApplicationContext基础上继承了Lifecycle接口,支持配置应用上下文,支持生命周期控制

           AbstractApplicationContext:ApplicationContext的抽象类实现,简单的实现了一些功能方法和通用骨架,使用模版方法模式,具体实现在子类中

                   AbstractRefreshableApplicationContext:  支持更新操作的抽象类(refresh操作AbstractApplicationContext只给出了基本骨架)

                            AbstractRefreshableConfigApplicationContext:可配置的AbstractRefreshableApplicationContext

XmlBeanDefinitionReader读取配置

                     ClassPathXmlApplicationContext:实现了getConfigResources方法的具体类

从继承线中可以看到,spring将只读接口和可配置接口进行了分层。(这样分层的具体优点?)

仔细看这些继承类的代码,我们会发现,虽然ApplicationContext实现了以下四大功能:

ListableBeanFactory)  
  
ResourceLoader)  
  
ApplicationEventPublisher)  
  
MessageSource)

但这些具体的逻辑实现并不是由ApplicationContext的实现类来具体实现,而是委托给ApplicationContext实现类内部的这些接口的实现对象来进行处理,ApplicationContext只提供一个外层的接口。比如BeanFactory的相关接口就是将请求转发给AbstractRefreshableApplicationContext中的DefaultListableBeanFactory类型的BeanFactory来具体实现的。这样的好处就是将接口的调用和实现隔离开。

既然和ioc相关的操作都会直接转发给DefaultListableBeanFactory类型的对象,那我们就必须了解DefaultListableBeanFactory的继承线:

不继承springboot父项目_加载_03

这里有三条比较重要的继承线:

其中一条是关于注册单例对象/bean定义接口作为顶级接口的继承线,如红线所示,主要就是给该类添加注册对象到该应用的ioc容器中的接口。

还有一条是用于在BeanFactory的基础上提供自动装配的功能的继承线,如黑线所示

最后一条是常规的关于BeanFactory和它的一些扩展接口的继承线

其中关于bean定义的对象的kv对保存在DefaultListableBeanFactory中,单例对象的kv对保存在DefaultSingletonBeanRegistry中。