Spring IOC-ApplicationContext的继承关系

来源:互联网 发布:电视台直播软件 编辑:程序博客网 时间:2024/05/22 13:49

前面的文章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.有盘符表示的是文件绝对路径.
两个类不同的构造

0 0