ClassPathXmlApplicationContext源码分析

ClassPathXmlApplicationContext源码解读

 

ClassPathXmlApplicationContext继承了AbstractXmlApplicationContext,实现了ApplicationContext接口。BeanFactory是所有容器的顶级接口,spring中所有容器都是基于BeanFactory的

ClassPathXmlApplicationContext源码:

package org.springframework.context.support;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

public class ClassPathXmlApplicationContext extends AbstractXmlApplicationContext {
  @Nullable
  private Resource[] configResources;

  public ClassPathXmlApplicationContext() {
  }

  public ClassPathXmlApplicationContext(ApplicationContext parent) {
      super(parent);
  }

  public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
      this(new String[]{configLocation}, true, (ApplicationContext)null);
  }

  public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
      this(configLocations, true, (ApplicationContext)null);
  }

  public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent) throws BeansException {
      this(configLocations, true, parent);
  }

  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh) throws BeansException {
      this(configLocations, refresh, (ApplicationContext)null);
  }

  public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
      super(parent);
      this.setConfigLocations(configLocations);
      if (refresh) {
          this.refresh();
      }

  }

  public ClassPathXmlApplicationContext(String path, Class<?> clazz) throws BeansException {
      this(new String[]{path}, clazz);
  }

  public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz) throws BeansException {
      this(paths, clazz, (ApplicationContext)null);
  }

  public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable 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);
      }

      this.refresh();
  }

  @Nullable
  protected Resource[] getConfigResources() {
      return this.configResources;
  }
}

ClassPathXmlApplicationContext

  1. public ClassPathXmlApplicationContext()`默认构造方法,创建一个实例

  1. public ClassPathXmlApplicationContext(ApplicationContext parent)创建一个实例并设置这个实例的父ApplicationContext为parent

  1. public ClassPathXmlApplicationContext(String configLocation)创建一个实例,并且设置一个配置文件的类路径

  1. public ClassPathXmlApplicationContext(String... configLocations)创建一个实例,并且设置零个或多个配置文件的类路径

  1. public ClassPathXmlApplicationContext(String[] configLocations, @Nullable ApplicationContext parent)创建一个实例,并且设置零个或多个配置文件的类路径,并设置这个实例的父ApplicationContext为parent

  1. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh)创建一个实例,并且设置零个或多个配置文件的类路径,同时根据refresh来判定是否需要自动刷新这个上下文(ApplicationContext)

  1. public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)创建一个实例,并且设置零个或多个配置文件的类路径,根据refresh来判定是否需要自动刷新这个上下文(ApplicationContext),于此同时设置这个实例的父ApplicationContext为parent

  1. public ClassPathXmlApplicationContext(String path, Class<?> clazz) 创建一个实例,并且设置一个配置文件的类路径(根据类clazz所在的位置)

  1. public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz)创建一个实例,并且设置零个或多个配置文件的类路径(根据类clazz所在的位置)

  1. public ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent)创建一个实例,并且设置零个或多个配置文件的类路径(根据类clazz所在的位置),并设置这个实例的父ApplicationContext为parent

ClassPathXmlApplicationContext类文件中只有一个属性Resource[] configResources(配置文件的集合)

一个公有方法用来获取所有的配置文件集合protected Resource[] getConfigResources()。

在上述十个构造方法中主要使用的是public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)和ClassPathXmlApplicationContext(String[] paths, Class<?> clazz, @Nullable ApplicationContext parent)其他的构造方法主要是调用上述两个方法。前者是根据默认的类路径加载配置文件、后者主要是通过给定类的路径来加载配置文件,并设置该应用上下文(ApplicationContext)的父应用上下文为parent,有所区别的是前者根据refresh参数来决定是否自动加载上下文,后者直接加载上下文。

测试:

@Test
  public void TestXmlBean(){
      ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("classpath:xmlRegBean.xml");
      Animal cat =context.getBean("cat", Cat.class);
      cat.getName();
  }

  @Test
  public void TestMultiXml(){
          ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("classpath:xmlRegBean.xml","classpath:xmlRegBean2.xml");
          Animal cat =context.getBean("cat", Cat.class);
          cat.getName();
          System.out.println(cat);
          Animal cat2 =context.getBean("cat2", Cat.class);
          cat2.getName();
          System.out.println(cat2);
  }
   
@Test
  public void TestArrayXml(){
      String[] arrXml = {"classpath:xmlRegBean.xml","classpath:xmlRegBean2.xml"};
      ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext(arrXml,true);
      Animal cat =context.getBean("cat", Cat.class);
      cat.getName();
      System.out.println(cat);
      Animal cat2 =context.getBean("cat2", Cat.class);
      cat2.getName();
      System.out.println(cat2);
  }

ClassPathXmlApplicationContext构造方法

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
      super(parent);
      this.setConfigLocations(configLocations);
      if (refresh) {
          this.refresh();
      }

AbstractXmlApplicationContext

refresh()方法完成了容器的初始化。

public void refresh() throws BeansException, IllegalStateException {
      synchronized(this.startupShutdownMonitor) {
          this.prepareRefresh();
          ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
          this.prepareBeanFactory(beanFactory);

          try {
              this.postProcessBeanFactory(beanFactory);
              this.invokeBeanFactoryPostProcessors(beanFactory);
              this.registerBeanPostProcessors(beanFactory);
              this.initMessageSource();
              this.initApplicationEventMulticaster();
              this.onRefresh();
              this.registerListeners();
              this.finishBeanFactoryInitialization(beanFactory);
              this.finishRefresh();
          } catch (BeansException var9) {
              if (this.logger.isWarnEnabled()) {
                  this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
              }

              this.destroyBeans();
              this.cancelRefresh(var9);
              throw var9;
          } finally {
              this.resetCommonCaches();
          }

      }
  }

ClassPathXmlApplicationContext直接继承的类只有AbstractXmlApplicationContext,继承关系

AbstractXmlApplicationContext

  1. public AbstractXmlApplicationContext()默认构造函数

  1. public AbstractXmlApplicationContext(@Nullable ApplicationContext parent)设置该上下文的父上下文为parent,ClassPathXmlApplicationContext的除了默认构造方法,其余所有构造方法都会调用该构造方法

AbstractXmlApplicationContext 包含一个private boolean validating = true,xml配置文件是否需要校验,默认为true。

AbstractXmlApplicationContext包含的方法有:

  1. protected Resource[] getConfigResources()返回所有的配置文件资源,ClassPathXmlApplicationContext有进行重写,默认为null。

  1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) 从给定的beanFactory加载bean的定义,即从xml或者其他文件中加载配置文件,这里值得是xml配置文件

  1. protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader)初始化给定的reader,这里主要是设置reader需要验证xml的格式。loadBeanDefinitions在执行的时候会调用该方法。

  1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)使用reader来加载配置文件中bean的定义。loadBeanDefinitions在执行的时候会调用该方法。

 

prepareRefresh()`:

上下文刷新的准备工作,完成一下工作

  1. 设置启动时间、是否关闭和是否激活

  1. 在上下文中初始化任何占位符属性资源

  1. 验证标记为必需的属性文件是可解析的

 protected void prepareRefresh() {
      this.startupDate = System.currentTimeMillis();
      this.closed.set(false);
      this.active.set(true);
      if (this.logger.isDebugEnabled()) {
          if (this.logger.isTraceEnabled()) {
              this.logger.trace("Refreshing " + this);
          } else {
              this.logger.debug("Refreshing " + this.getDisplayName());
          }
      }

ConfigurableListableBeanFactory beanFactory:创建DefaultListableBeanFactory实例,解析xml配置文件,注册bean

prepareBeanFactory(beanFactory):对BeanFactory进行各种功能填充 在此方法中,增加的支持@Qualifier与@Autowired这两个注解

postProcessBeanFactory(beanFactory):由子类实现,可进行自定义扩展

invokeBeanFactoryPostProcessors(beanFactory):激活BeanFactory的处理器

registerBeanPostProcessors(beanFactory):Register bean processors that intercept bean creation

initMessageSource():初始化message资源

initApplicationEventMulticaster()为这个context初始化一个事件广播器

beanonRefresh():由子类实现,初始化其他

BeanregisterListeners(); 注册已实现ApplicationListener接口的

beanfinishBeanFactoryInitialization(beanFactory);实例化所有非延迟初始化的单例模式

finishRefresh()完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知监听者

AbstractXmlApplicationContext类也只有一个父类AbstractRefreshableConfigApplicationContext

AbstractRefreshableConfigApplicationContext同样也是一个抽象类,他所拥有的构造方法为

  1. public AbstractRefreshableConfigApplicationContext()默认构造方法

  1. public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent)设置父上下文为parent,ClassPathXmlApplicationContext初始化时会调用该构造方法。

该类包含的属性有:

  1. private String[] configLocations 配置文件路径

  1. private boolean setIdCalled = false,是否需要设置该上下文的名字

该类包含的方法:

  1. public void setConfigLocation(String location),设置配置文件,多个配置文件以,;\t\n作为分割符

  1. public void setConfigLocations(@Nullable String... locations),设置配置文件ClassPathXmlApplicationContext初始化时会调用该方法

  1. protected String[] getConfigLocations()获取所有配置文件路径

  1. protected String[] getDefaultConfigLocations()默认配置文件默认为null

  1. public void setBeanName(String name)设置该bean的name,此方法为实现继承的BeanNameAware接口

  1. public void setId(String id)设置该上下文的id

  1. public void afterPropertiesSet()该方法为初始化完成该bean之后,执行该方法,此方法为实现接口InitializingBean中的方法。

  1. protected String resolvePath(String path)替换path中的占位符(${})

 

AbstractRefreshableConfigApplicationContext也只有一个父类AbstractRefreshableApplicationContext,但是实现了两个接口BeanNameAware和InitializingBean,AbstractRefreshableApplicationContext AbstractRefreshableApplicationContext同样也是一个抽象类、其构造函数包括:

AbstractRefreshableApplicationContext

  1. public AbstractRefreshableApplicationContext()默认构造方法

  1. public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent)设置该上下文的父上下文为parent,ClassPathXmlApplicationContext实例化的时候会调用该方法

 

AbstractRefreshableApplicationContext包含的属性

  1. private Boolean allowBeanDefinitionOverriding是否允许覆盖注册的bean定义

  1. private Boolean allowCircularReferences;是否允许循环依赖

  1. private DefaultListableBeanFactory beanFactory 当前上下文的bean工厂

  1. private final Object beanFactoryMonitor = new Object()内部 bean工厂监视器

AbstractRefreshableApplicationContext包含的方法有:

  1. public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding)设置是否允许有相同名字的bean定义

  1. public void setAllowCircularReferences(boolean allowCircularReferences)设置是否允许循环依赖

  1. protected final void refreshBeanFactory()重新刷新上下文,首先关闭之前的上下文、然后创建新的

  1. protected void cancelRefresh(BeansException ex)取消上下文刷新

  1. protected final void closeBeanFactory()关闭bean工厂

  1. protected final boolean hasBeanFactory()上下文是否有bean工厂

  1. public final ConfigurableListableBeanFactory getBeanFactory()获取bean工厂

  1. protected DefaultListableBeanFactory createBeanFactory()创建bean工厂

  1. protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory)设置bean工厂

  1. protected abstract void loadBeanDefinitions从配置文件中加载bean的定义

 

AbstractRefreshableApplicationContext的父类只有AbstractApplicationContext,AbstractApplicationContext

AbstractApplicationContext是抽象类,其构造函数有

  1. public AbstractApplicationContext()默认构造方法

  1. public AbstractApplicationContext(@Nullable ApplicationContext parent)设置父上下文为parent,

ClassPathXmlApplicationContext初始化时会调用该方法

AbstractApplicationContext的属性包含:

  1. private ApplicationContext parent上下文(层级结构)的父想上下文

  1. private ConfigurableEnvironment environment环境变量主要是properties文件中配置的参数

  1. private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors bean工厂的后置处理器列表

  1. private long startupDate 上下文启动时间

  1. private final AtomicBoolean active 上下文是否已经启动

  1. private final AtomicBoolean closed 上下文是否关闭

  1. private final Object startupShutdownMonitor保证启动和销毁线程安全的对象

AbstractApplicationContext包含的方法有:

  1. public ApplicationContext getParent()返回该上下文的父上下文

  1. protected ConfigurableEnvironment createEnvironment()创建环境变量实例,如果环境变量为空则创建

  1. public AutowireCapableBeanFactory getAutowireCapableBeanFactory()获取拥有自动注入的bean工厂

  1. public long getStartupDate() 获取上下文启动时间

  1. public void publishEvent(ApplicationEvent event)发布ApplicationEvent类型的事件给所有的listener

  1. public void publishEvent(Object event)发布事件给所有的listener

  1. protected void publishEvent(Object event, @Nullable ResolvableType eventType)发布事件给所有的listener

  1. ApplicationEventMulticaster getApplicationEventMulticaster()获取上下文的ApplicationEventMulticaster

  1. LifecycleProcessor getLifecycleProcessor()获取上下文的LifecycleProcessor

  1. protected ResourcePatternResolver getResourcePatternResolver()资源解析器

  1. public void setParent(@Nullable ApplicationContext parent)设置上下文的父上下文

  1. public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor)添加BeanFactoryPostProcessor

  1. public void addApplicationListener(ApplicationListener<?> listener)添加listener

  1. public void refresh()整个加载的核心逻辑

  1. protected void prepareRefresh()核心逻辑之前的操作

  1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory()获取

ConfigurableListableBeanFactory

  1. protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) 初始化bean工厂前执行

  1. protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)调用bean工厂的后置处理器

  1. protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)注册bean后置处理器

  1. protected void initMessageSource()初始化消息资源

  1. protected void finishBeanFactoryInitialization完成bean工厂的初始化操作

  1. protected void finishRefresh()完成刷新后的操作

 

AbstractApplicationContext的父类

AbstractApplicationContext只继承了DefaultResourceLoader和实现接口:ConfigurableApplicationContext

DefaultResourceLoader的继承结构为:

 

posted @ 2019-12-25 11:49  凌林的芳香  阅读(417)  评论(0编辑  收藏  举报