Spring IOC-ApplicationContext的继承关系

前面的文章Spring IOC-BeanFactory的继承体系分享了BeanFactory的所有接口,抽象类以及实现类的主要方法及层级关系。今天我们分享BeanFactory的相当于一个分支ApplicationContext。
既然是继承,那么肯定拥有BeanFactory核心功能比如一系列的getBean()功能,不同之处在于扩展了一些功能(比如加载bean定义的方式)和增加了一些功能(比如事件的支持,国际化的支持、消息的支持,应用环境的集合)。而功能的扩展肯定是反映在代码上,我们直接看代码。
首先是源头的ApplicationContext接口:

// 除了包含BeanFactory的所有功能之外,在国际化支持(MessageSource)、资源访问(如URL和文件)(ResourcePatternResolver)、事件传播(ApplicationEventPublisher)等方面进行了良好的支
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
        //环境的唯一id
        String getId();
        //环境的名称
        String getDisplayName();
        //环境第一次加载的时间
        long getStartupDate();
        //继承自HierarchicalBeanFactory
        ApplicationContext getParent();
        //相当于web环境实现的bean工厂
        AutowireCapableBeanFactory getAutowireCapableBeanFactory() ;
}

通过代码我们知道bean工厂的功能只是这个接口的一项子功能,特色的地方在于问绕bean工厂可以提供很多很使用的附加功能。
直接子类接口为ConfigurableApplicationContext,看下代码:

//是一个SPI服务提供者接口,提供配置功能的ApplicationContext,可以配置Context进行的环境、添加监听器、PostProcessor处理器、动态刷新、关闭等功能
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle {
    void setId(String id);
    //配置Context进行的环境
    void setEnvironment(ConfigurableEnvironment environment);
    void setParent(ApplicationContext parent);
    //PostProcessor处理器
    void addBeanFactoryPostProcessor(BeanFactoryPostProcessor beanFactoryPostProcessor);
    //添加监听器
    void addApplicationListener(ApplicationListener listener);
    //动态刷新
    void refresh() throws BeansException;
    void close();
}

好的,这个层级关系的接口已经说完,下面看第一级抽象类AbstractApplicationContext。这个类提供了一些方法的默认实现,其中继承自BeanFactory接口方法都委托这个环境下持有的BeanFactory对象去实现,比如

public Object getBean(String name) throws BeansException {
        return getBeanFactory().getBean(name);
}

这个类只是提供ApplicationContext中增加功能的默认实现。比如:

………………
public void setId(String id) {
    this.id = id;             
}                                                    
public void setEnvironment(ConfigurableEnvironment environment) {
    this.environment = environment;                              
}         
/**                                                                        
 * 负责存放FrameworkServlet中设置进来的监听器,当然只能是子类,因为这是抽象的。                          
 * 当然都可以设置监听器                                                              
 */                                                                        
public void addApplicationListener(ApplicationListener listener) {      
    if (this.applicationEventMulticaster != null) {                        
        this.applicationEventMulticaster.addApplicationListener(listener); 
    }                                                                      
    else {                                                                 
        this.applicationListeners.add(listener);                           
    }                                                                      
} 
public void refresh() throws BeansException, IllegalStateException {          
    synchronized (this.startupShutdownMonitor) {                              
        // Prepare this context for refreshing.                               
        prepareRefresh();                                                     
        //会调用XmlWebApplicationContext.loadBeanDefinitions()方法                 
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
        // 准备bean工厂                                                           
        prepareBeanFactory(beanFactory);                                      
        try {                                                                 
            // Allows post-processing of the bean factory in context subclasse
            postProcessBeanFactory(beanFactory);                               
            //对beanFactory对象本身调用在此环境中注册的processors                            
            invokeBeanFactoryPostProcessors(beanFactory);                         
            //注册所有的对bean的processors                                           
            registerBeanPostProcessors(beanFactory);                          
            // Initialize message source for this context.                    
            //初始化国际化支持的bean                                                   
            initMessageSource();                                                          
            //初始化时间发布器                                                        
            initApplicationEventMulticaster();                                 
            //刷新之后执行的操作                                                       
            onRefresh();                                                                          
            //注册事件,从bean工厂得到或者这个类设置进来的                                        
            registerListeners();                                                       
            //实例化所有单例的bean                                                    
            finishBeanFactoryInitialization(beanFactory);                     
            // Last step: publish corresponding event.                        
            finishRefresh();                                                  
        }                                                                                                                                       
        catch (BeansException ex) {                                           
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();                                                   
            // Reset 'active' flag.                                           
            cancelRefresh(ex);                                                
            // Propagate exception to caller.                                 
            throw ex;                                                         
        }                                                                     
    }                                                                         
}                                                                                                                                                                                                             
………………

其实这个类的主要的作用就是实现了refresh()方法。
下面我们俩看这个类的几个抽象方法,因为这往往是子类的价值所在:

protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
protected abstract void closeBeanFactory();
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

然后看子类具体的实现——AbstractRefreshableApplicationContext

protected final void refreshBeanFactory() throws BeansException { 
    if (hasBeanFactory()) {                                       
        destroyBeans();//先将所有的单例的bean destroy                     
        closeBeanFactory();//this.beanFactory = null;             
    }                                                             
    try {                                                         
        //实例化一个工厂,这里是DefaultListableBeanFactory                   
        DefaultListableBeanFactory beanFactory = createBeanFactory();         //org.springframework.web.context.WebApplicationContext:/
        beanFactory.setSerializationId(getId());                  
        customizeBeanFactory(beanFactory);                        
        //调用.XmlWebApplicationContext 的方法                         
        //在本类中是抽象方法,需要子类AbstractXmlApplicationContext中实现          
        loadBeanDefinitions(beanFactory);                         
        synchronized (this.beanFactoryMonitor) {                  
            this.beanFactory = beanFactory;                       
        }                                                         
    }                                                                                                                         
}                                                                 

再次找到需要子类实现的方法loadBeanDefinitions(beanFactory);直接找到子类AbstractXmlApplicationContext中实现代码:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory){
………………
//这和在BeanFactory中的加载过程一样,也是委托给XmlBeanDefinitionReader去读取配置文件,
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
………………
//加载bean定义
loadBeanDefinitions(beanDefinitionReader);
………………
}

在来看loadBeanDefinitions()方法:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
    ////getConfigResources()方法的实现再次交给子类,就是读取的配置文件的源——ClassPathXmlApplicationContext
    Resource[] configResources = getConfigResources();            
    if (configResources != null) {  
        //读取配置文件都是用的这个方法,和BeanFactory是一样的                              
        reader.loadBeanDefinitions(configResources);              
    }                                                             
    String[] configLocations = getConfigLocations(); 
    //照顾的是FileSystemXmlApplicationContext类             
    if (configLocations != null) {                                
        reader.loadBeanDefinitions(configLocations);              
    }                                                             
}                                                                 

在来看具体子类ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,这个类比较简单,功能就是实现父类的getConfigResources()方法,就是加载读取的资源。加载的过程在构造的时候发生:

  • ClassPathXmlApplicationContext中实现
public ClassPathXmlApplicationContext(String[] paths, Class clazz, ApplicationContext parent)
        throws BeansException {                                                              

    super(parent);                                                                           
    Assert.notNull(paths, "Path array must not be null");                                    
    Assert.notNull(clazz, "Class argument must not be null");                                
    this.configResources = new Resource[paths.length];                                       
    for (int i = 0; i < paths.length; i++) {                                                 
        this.configResources[i] = new ClassPathResource(paths[i], clazz);                    
    }     
    //加载完资源文件之后就刷新工厂环境                                                                                   
    refresh();                                                                               
}                                                                                            
  • FileSystemXmlApplicationContext中的实现
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {                                                                             
    super(parent);                                                                                          
    //简单的将路径设置到父类AbstractRefreshableConfigApplicationContext中                                               
    setConfigLocations(configLocations);                                                                    
    if (refresh) {                                                                                          
        refresh();                                                                                          
    }                                                                                                       
}                                                                                                           

下面在补充ClassPathXmlApplicationContext和FileSystemXmlApplicationContext的区别:
ClassPathXmlApplicationContext[只能读放在web-info/classes目录下的配置文件],classpath:前缀是不需要的,默认就是指项目的classpath路径下面;如果要使用绝对路径,需要加上file:前缀表示这是绝对路径;
对于FileSystemXmlApplicationContext,默认表示的是两种,如果要使用classpath路径,需要前缀classpath:
1.没有盘符的是项目工作路径,即项目的根目录;
2.有盘符表示的是文件绝对路径.
Spring IOC-ApplicationContext的继承关系_第1张图片

你可能感兴趣的:(Spring,IOC)