Spring源码学习笔记(3)——容器的功能扩展

时间:2022-07-24
本文章向大家介绍Spring源码学习笔记(3)——容器的功能扩展,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Spring源码学习笔记(3)——容器的功能扩展

一. 引入ApplicationContext接口

  1. 前面的介绍都是基于BeanFactory接口和它的默认实现XmlBeanFactory的,但是Spring体系中还有一个重要的接口:ApplicationContext。ApplicationContext在BeanFactory上进行了一些扩展,功能更为强大。可以理解为:BeanFactory是Spring容器内部使用的,而ApplicationContext是暴露给应用使用的。除非在一些特殊情况下,否则Spring建议使用ApplicationContext接口的实现类。
  2. 示例程序 以一段几乎每个Java程序员都写过的代码为例:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
  1. ClassPathXmlApplicationContext可以支持多个配置路径,在setConfigLocations()方法中进行处理,后续功能都在refresh()方法中:
public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {

    super(parent);
    //设置配置路径
    setConfigLocations(configLocations);

    if (refresh) {
        refresh();
    }
}
  1. 下面重点分析refresh()方法。

二. 整体流程

  1. refresh()的实现在AbstractApplicationContext类中,这是ApplicationContext体系中十分重要的一个方法,在整体上定义了ApplicationContext容器的启动流程:
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
    //准备带刷新的上下文环境
       prepareRefresh();

       //初始化BeanFactory,并读取Spring配置文件
       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

       //对初始化BeanFactory进行各种功能的填充
       prepareBeanFactory(beanFactory);

       try {
           //提供给子类的模板方法,可做额外处理
           postProcessBeanFactory(beanFactory);

           //激活容器中注册的处理器,进行各种处理
           invokeBeanFactoryPostProcessors(beanFactory);

           //注册BeanPosyProcesor后处理器,拦截Bean的创建过程。这里只是注册,并未执行
           registerBeanPostProcessors(beanFactory);

            //为容器初始化各种Message源,即多语言、国际化处理
           initMessageSource();

           //初始化消息广播器,将applicationEventMulticaster注册到单例容器中,为容器的消息机制做准备
           initApplicationEventMulticaster();

           //提供给子类的模板方法,可初始化其他Bean
           onRefresh();

        //在所有注册的Bean中查找Listener Bean,注册到消息广播器applicationEventMulticaster中
           registerListeners();

           //初始化剩余的单例Bean(非lazy-init的)
           finishBeanFactoryInitialization(beanFactory);

           //最后一步:完成容器刷新过程,通知容器中的LifecycleProcessor刷新完成,并且发布ContextRefreshedEvent容器刷新完成事件
           finishRefresh();
       }

       //异常处理
       catch (BeansException ex) {
           if (logger.isWarnEnabled()) {
               logger.warn("Exception encountered during context initialization - " +
                           "cancelling refresh attempt: " + ex);
           }

           destroyBeans();

           cancelRefresh(ex);

           throw ex;
       }

       finally {
           //清空Spring通用缓存
           resetCommonCaches();
       }
   }
}
  1. 可以看到,整个refresh()的流程是很清晰的,处理异常处理外,大概做了这么几件事:
    1. 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。 在某些情况下,项目的运行需要读取某些系统变量,这些变量的设置可能会影响系统的正确性,此时prepareRefresh()这个方法就可以发挥它的作用,在容器启动时(一般也是项目启动时)为我们检查这些变量的设置。
    2. 初始化BeanFactory,并读取XML配置文件 在这一步中会复用BeanFactory的读取配置文件和加载Bean的过程,在这一步之后,ApplicationContext实际上就包含了所有BeanFactory所提供的功能,可以进行Bean的提取等工作了。
    3. 对BeanFactory进行各种功能的填充
    4. 提供给子类模板方法,做额外的扩展
    5. 激活各种FactoryBean进行处理
    6. 注册BeanPostProcessor后处理器,这里只是注册,真正调用是在getBean()时
    7. 为上下文初始化Message源,处理多语言和国际化
    8. 初始化应用消息广播器ApplicationEventMulticaster,为Spring消息机制做准备
    9. 提供给子类模板方法,初始化其他的Bean
    10. 在所有注册的Bean中查找ApplicationListener,注册到ApplicationEventMulticaster
    11. 初始化其余的非延迟加载的单实例Bean
    12. 完成容器刷新过程,通知LifecycleProcessor,并发布ContextRefreshedEvent容器刷新完成事件
  2. 下面仔细分析具体每一步的处理逻辑

三. 环境准备

  1. 查看方法实现:
protected void prepareRefresh() {
   this.startupDate = System.currentTimeMillis();
   this.closed.set(false);
   this.active.set(true);

   if (logger.isInfoEnabled()) {
       logger.info("Refreshing " + this);
   }

   //初始化placeholder属性源,默认空实现,留给子类覆盖
   initPropertySources();

   //校验所有需要的属性文件是否都已经放入环境中
   getEnvironment().validateRequiredProperties();

   //为early的容器事件做准备
   this.earlyApplicationEvents = new LinkedHashSet<>();
}
  1. 这个方法的核心逻辑默认都是空实现,可以交给子类去覆盖,例如我们可以自定义一个ApplicationContext,并且校验自己的属性文件和系统变量配置

四. 加载BeanFactory

  1. 前面说过,ApplicationContext是对BeanFactory功能上的扩展,不但包含了BeanFactory的全部功能,更是在其基础上添加了大量的扩展应用,obtainFreshBeanFactory()正是实现了BeanFactory的地方,在这个方法之后,ApplicationContext方法就拥有了BeanFactory的全部功能。代码实现:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   //初始化BeanFactory,并进行XML文件读取,而且将得到的BeanFactory记录在当前实体的属性中
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
       logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}
  1. 核心逻辑委托给了AbstractRefreshableApplicationContext的refreshBeanFactory()方法实现:
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
       destroyBeans();
       closeBeanFactory();
   }
   try {
       //创建DefaultListableBeanFactory
       DefaultListableBeanFactory beanFactory = createBeanFactory();

       //指定序列化id,如果需要的话,可以根据序列化id反序列化出BeanFactory对象
       beanFactory.setSerializationId(getId());

       //定制BeanFactory相关属性,
       customizeBeanFactory(beanFactory);

       //初始化DocumentReader,进行配置文件的读取和解析
       loadBeanDefinitions(beanFactory);
       synchronized (this.beanFactoryMonitor) {
           this.beanFactory = beanFactory;
       }
   }
   catch (IOException ex) {
       throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}
  1. refreshBeanFactory()的具体步骤:
    1. 创建DefaultListableBeanFactory DefaultListableBeanFactory是比较基础的BeanFactory类型。
    2. 设置序列化id。
    3. 定制BeanFactory,是对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖和是否允许循环引用的支持。
    4. 读取配置文件,加载BeanDefinition,该方法交给子类重写,如AbstractXmlApplicationContext类中实现了读取XML文件加载BeanDefinition的处理。
    5. 使用全局变量beanFactory记录BeanFactory实例

五. 对初始化好的BeanFactory进行各种功能的填充

  1. 对于上面初始化好的BeanFactory,进行一些属性的设置和功能上的扩展,具体逻辑在prepareBeanFactory()中:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   //设置BeanFactory的ClassLoader为当前ApplicationContext的ClassLoader
   beanFactory.setBeanClassLoader(getClassLoader());

   //设置BeanFactory的表达式语言处理器,支持表达式语言
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

   //为BeanFactory设置一个默认的PropertyEditor,这个主要是对Bean的属性等设置管理的一个工具
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   //添加后处理器
   beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

   //设置几个忽略自动装配的接口
   beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
   beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
   beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
   beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
   beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

   //设置几个自动装配的特殊规则
   beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
   beanFactory.registerResolvableDependency(ResourceLoader.class, this);
   beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
   beanFactory.registerResolvableDependency(ApplicationContext.class, this);

   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   //增加AspectJ的支持
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
       beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }

   //注册默认的系统Bean
   if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
       beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
       beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
   }
   if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
       beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
   }
}
  1. 该方法主要对BeanFactory进行了以下几个方面的扩展:
    1. 对SPEL表达式的支持
    2. 对属性编辑器的支持
    3. 增加对一些内置类,如EnvironmentAware、MessageSourceAware的信息注入
    4. 对AspectJ的支持

六. BeanFactory的后处理

  1. BeanFactoryPostProcessor 在BeanFactory的定制化完成之后,开始执行BeanFactory的后处理,后处理主要依赖BeanFactoryPostProcessor类进行。BeanFactoryPostProcessor的功能类似于BeanPostProcessor,可以对Bean的定义(配置元数据)进行处理,也就是说,Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何其他的Bean之前读取配置元数据,并可能修改它。BeanFactoryPostProcessor与BeanPostProcessor的主要区别在于,BeanFactoryPostProcessor是容器级别的,它的处理依赖于当前的BeanFactory,而且不要通过BeanFactoryPostProcessor进行Bean实例化的相关处理,BeanFactoryPostProcessor只能处理BeanDifinition。
  2. 激活BeanFactoryPostProcessor 下面回到refresh()方法的处理,调用invokeBeanFactoryPostProcessors()激活容器中注册的BeanFactoryPostProcessor:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
       beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}
  1. 核心方法为PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()),调用容器中所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。

七. 注册BeanPostProcessor

  1. ApplicationContext在registerBeanPostProcessors()方法中注册了BeanPostProcessor,这里只是注册,并不是调用,真正的调用实在创建Bean的时候处理的。这是一个重要的步骤,也是BeanFactory不支持BeanPostProcessor的原因:BeanFactory中没有实现后处理器的自动注册,只能手动注册。
  2. 具体实现:
public static void registerBeanPostProcessors(
   ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取所有BeanPostProcessor的Bean Name
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   //向容器中注册BeanPostProcessorChecker后处理器,只是一个普通的打印
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   //使用priorityOrderedPostProcessors保证顺序
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();

   //使用orderedPostProcessorNames保证顺序
   List<String> orderedPostProcessorNames = new ArrayList<>();

   //无序的BeanPostProcessors
   List<String> nonOrderedPostProcessorNames = new ArrayList<>();


   for (String ppName : postProcessorNames) {
       if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
           BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
           priorityOrderedPostProcessors.add(pp);
           if (pp instanceof MergedBeanDefinitionPostProcessor) {
               internalPostProcessors.add(pp);
           }
       }
       else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
           orderedPostProcessorNames.add(ppName);
       }
       else {
           nonOrderedPostProcessorNames.add(ppName);
       }
   }

   //1.排序,注册所有实现了PriorityOrdered接口的有序BeanPostProcessor
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   //2.排序,注册所有实现了Ordered接口的有序BeanPostProcessor
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
   for (String ppName : orderedPostProcessorNames) {
       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
       orderedPostProcessors.add(pp);
       if (pp instanceof MergedBeanDefinitionPostProcessor) {
           internalPostProcessors.add(pp);
       }
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   //3.注册无序的BeanPostProcessor
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
   for (String ppName : nonOrderedPostProcessorNames) {
       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
       nonOrderedPostProcessors.add(pp);
       if (pp instanceof MergedBeanDefinitionPostProcessor) {
           internalPostProcessors.add(pp);
       }
   }
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    //最后,注册实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor
   sortPostProcessors(internalPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   //注册ApplicationListenerDetector探测器
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

八. 后续步骤

  1. 初始化消息资源
  2. 初始化ApplicationEventMulticaster,为Spring的Event体系提供支持。 当发布容器事件时,会默认使用SimpleApplicationEventMulticaster对事件进行广播,遍历所有的ApplicationListener,回调ApplicationListener的onApplicationEvent()方法处理事件。每个监听器都可以监听到容器发布的所有事件,但是是否处理由监听器逻辑决定。
  3. 注册监听器 上面提到的Event体系中的监听器,就是在这里注册的。
  4. 初始化非延迟加载的单例Bean
  5. 容器刷新完成