Spring源码之容器的功能扩展和refresh方法解析

容器的功能扩展和refresh方法解析

在之前文章中我们了解了关于Spring中bean的加载流程,并一直使用BeanFactory接口以及它的默认实现类XmlBeanFactory,在Spring中还提供了另一个接口ApplicationContext,用于扩展BeanFactory中现有的功能。

首先BeanFactory和ApplicationContext都是用于加载bean的,但是相比之下,ApplicationContext提供了更多的扩展功能,ApplicationContext包含了BeanFactory的所有功能。通常我们会优先使用ApplicationContext。

我们来看看ApplicationContext多了哪些功能?

首先看一下写法上的不同。

使用BeanFactory方式加载XML

final BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

使用ApplicationContext方式加载XML

final ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");

我们开始点开ClassPathXmlApplicationContext的构造函数,进行分析。

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

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}

在ClassPathXmlApplicationContext中可以将配置文件路径以数组的形式传入,对解析及功能实现都在refresh()方法中实现。

设置配置路径

public void setConfigLocations(@Nullable String... locations) {
   if (locations != null) {
      Assert.noNullElements(locations, "Config locations must not be null");
      this.configLocations = new String[locations.length];
      for (int i = 0; i < locations.length; i++) {
         this.configLocations[i] = resolvePath(locations[i]).trim();
      }
   }
   else {
      this.configLocations = null;
   }
}

此函数主要解析给定的路径数组,如果数组中包含特殊符号,如${var},那么在resolvePath方法中会搜寻匹配的系统变量并替换。

扩展功能

设置完路径后,就可以对文件进行解析和各种功能的实现,可以说在refresh方法中几乎包含了ApplicationContext中提供的全部功能,而且此函数的逻辑也十分清晰,可以很容易分析对应层次和逻辑。

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 准备刷新的上下文环境,包括设置启动时间,是否激活标识位
      // 初始化属性源(property source)配置
      prepareRefresh();

      // 初始化BeanFactory 并进行xml文件读取
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

      try {
         // 子类覆盖方法做额外的处理
         postProcessBeanFactory(beanFactory);

         // 激活各种BeanFactory处理器
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册拦截bean创建的bean处理器,只是注册,具体调用在getBean中
         registerBeanPostProcessors(beanFactory);

         // 为上下文初始化Message源,国际化处理
         initMessageSource();

         // 初始化应用消息广播器,并放入applicationEventMulticaster bean中
         initApplicationEventMulticaster();

         // 留给子类来初始化其他的bean
         onRefresh();

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

         // 初始化剩下的单例bean (非惰性)
         finishBeanFactoryInitialization(beanFactory);

         //完成刷新过程,通知生命周期处理器LifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人
         finishRefresh();
      }

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

         // 销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
         destroyBeans();

         // 重置活动标志
         cancelRefresh(ex);

         throw ex;
      }

      finally {
         //重置公共缓存
         resetCommonCaches();
      }
   }
}

我们总结一下初始化的步骤。

  1. 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证
  2. 初始化BeanFactory,并对XML文件进行读取。之前我们说过ClassPathXmlApplicationContext中包含着BeanFactory所提供的一切特征,那么在这一步将会复用BeanFactory中的配置文件读取解析及其他功能,在这一步之后ClassPathXmlApplicationContext就已经包含了BeanFactory所提供的功能,也就是可以对bean进行提取等操作
  3. 对BeanFactory进行各种功能填充
  4. 子类覆盖方法做额外的处理。主要用于我们在业务上做进一步扩展
  5. 激活各种BeanFactory处理器
  6. 注册拦截bean创建的bena处理器,这里仅仅是注册,真正调用在getBean中
  7. 为上下文初始化Message源,对不同语言的消息体进行国际化处理
  8. 初始化应用消息广播器,并放入"applicationEventMulticaster" bean中
  9. 留给子类来初始化其他的bean
  10. 在所有注册的bean中查找listener bean,注册到消息广播器中
  11. 初始化剩下的单实例(非惰性)
  12. 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent来通知别人

环境准备

prepareRefresh方法主要做些准备工作,比如对系统属性及环境变量的初始化及验证。

Spring源码之容器的功能扩展和refresh方法解析

  1. initPropertySources

该方法里面是一个空实现,主要用于给我们根据需要去重写该方法,并在方法中进行个性化的属性处理及设置。

protected void initPropertySources() {
        // For subclasses: do nothing by default.
}
  1. validateRequiredProperties 该方法主要对属性进行验证。默认情况下什么也没校验。在我们继承了ClassPathXmlApplicationContext类重写了initPropertySources方法后会进行相关校验。

加载BeanFactory

obtainFreshBeanFactory 方法主要用来获取BeanFactory,刚才说过ApplicationContext拥有BeanFactory的所有功能,这个方法就是实现BeanFactory的地方,也就是说调用完该方法后,applicationContext就拥有了BeanFactory的功能。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   //初始化BeanFactory,并进行XML文件读取,将得到的BeanFactory记录到当前实体属性中
   refreshBeanFactory();
   //返回当前实体的beanFactory属性
   return getBeanFactory();
}
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

我们进入AbstractRefreshableApplicationContext#refreshBeanFactory()方法中。

protected final void refreshBeanFactory() throws BeansException {
        //判断是否存在beanFactory
        if (hasBeanFactory()) {
            //销毁所有单例
            destroyBeans();
            //重置beanFactory
            closeBeanFactory();
        }
        try {
            //创建beanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            //设置序列化id
            beanFactory.setSerializationId(getId());
            //定制beanFactory,设置相关属性,包括是否允许覆盖同名称不同定义的对象以及循环依赖
            customizeBeanFactory(beanFactory);
            //初始化DocumentReader,进行XML读取和解析
            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. 创建DefaultListableBeanFactory。声明方式为:BeanFactory bf = new XmlBeanFactory("beanFactoryTest.xml"),其中的XmlBeanFactory继承自DefaultListableBeanFactory,并提供了XmlBeanDefinitionReader类型的reader属性,也就是说DefaultListableBeanFactory是容器的基础,必须首先实例化,这里就是实例化DefaultListableBeanFactory的步骤
  2. 指定序列化ID
  3. 定制BeanFactory
  4. 加载BeanDefinition
  5. 使用全局变量记录BeanFactory类实例

定制BeanFactory

首先我们先了解customizeBeanFactory方法,该方法是在基本容器的基础上,增加了是否允许覆盖、是否允许扩展的设置。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   //如果不为空,设置beanFactory对象响应的属性,含义:是否允许覆盖同名称的不同定义的对象
   if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   //如果属性不为空,设置给beanFactory对象相应属性,含义:是否允许bean之间存在循环依赖
   if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

具体这里只是做了简单的判断,具体设置属性的地方,使用子类覆盖即可。例如:

/**
 * @author 神秘杰克
 * 公众号: Java菜鸟程序员
 * @date 2022/6/12
 * @Description 自定义ClassPathXmlApplicationContext
 */
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {

   @Override
   protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
      super.setAllowBeanDefinitionOverriding(false);
      super.setAllowCircularReferences(false);
      super.customizeBeanFactory(beanFactory);
   }
}

加载BeanDefinition

在初始化了DefaultListableBeanFactory后,我们还需要XmlBeanDefinitionReader来读取XML文件,这个步骤中首先要做的就是初始化XmlBeanDefinitionReader。

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   //为指定beanFactory创建XmlBeanDefinitionReader
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   //进行环境变量的设置
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   //对beanDefinitionReader进行设置,可以覆盖
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

初始化了DefaultListableBeanFactory和XmlBeanDefinitionReader后,我们就可以进行配置文件的读取了。最终XmlBeanDefinitionReader所去读的BeanDefinitionHolder都会注册到DefaultListableBeanFactory中。

经过该方法后类型为DefaultListableBeanFactory中的变量beanFactory已经包含了所有解析好的配置。关于配置文件的读取这一部分之前文章已经讲过,这里就不再赘述。

功能扩展

我们在完成了配置文件解析后,我们接着进入prepareBeanFactory方法。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   //设置beanFactory的ClassLoader为当前context的ClassLoader
   beanFactory.setBeanClassLoader(getClassLoader());
   //设置beanFactory的表达式语言处理
   beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
   //为beanFactory增加了一个默认的propertyEditor,主要是对bean的属性等设置管理的一个工具
   beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

   //添加BeanPostProcessor
   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);

   //增加了ApplicationListenerDetector主要是检测bean是否实现了ApplicationListener接口
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

   //增加对AspectJ的支持
   if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      // Set a temporary ClassLoader for type matching.
      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());
   }
}

该方法主要做了几个方面的扩展:

BeanFactory的后处理

BeanFactory作为Spring中容器的基础,用于存放所有已经加载的bean,为了保证程序的高扩展性,Spring针对BeanFactory做了大量的扩展,比如PostProcessor等都是在这里实现的。

激活注册的BeanFactoryPostProcessor

在学习之前,我们先了解一下BeanFactoryPostProcessor的用法。BeanFactoryPostProcessor接口和BeanPostProcessor类似,可以对bean的定义进行处理。也就是说,Spring IOC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取配置元数据,并可以修改它。BeanFactoryPostProcessor可以配置多个,通过实现Ordered接口设置“order”来控制执行顺序。

需要注意的是如果在容器中定义一个BeanFactoryPostProcessor,它仅仅对此容器中的bean进行后置处理。BeanFactoryPostProcessor不会对其他容器中的bean进行后置处理。

1.BeanFactoryPostProcessor的典型应用:PropertySourcesPlaceholderConfigurer

首先我们来看一下配置文件:


   
      ${bean.msg}
   

在里面我们使用到了变量引用:${bean.msg},这就是Spring的分散配置,我们可以在配置文件中配置该属性的值。

application.properties

bean.msg=hi

然后我们再进行配置文件的配置。


        
            
                application.properties
            
        
    

这时候就明白了,我们通过PreferencesPlaceholderConfigurer中进行获取我们的配置信息。我们查看该类可以知道间接性继承了BeanFactoryPostProcessor接口。

当Spring加载任何实现了这个接口的bean时,都会在bean工厂加载所有bena的配置之后执行postProcessBeanFactory方法。在方法中先后调用了mergeProperties、convertProperties、processProperties这三个方法,分别得到配置、将得到的配置进行转换为合适的类型、最后将配置内容告知BeanFactory。

正是通过实现BeanFactoryPostProcessor,BeanFactory会在实例化任何bean之前获得配置信息,从而能够正确解析bean配置文件中的变量引用

PropertySourcesPlaceholderConfigurer已经取代了PropertyPlaceholderConfigurer,因为汇聚了Environment、多个PropertySource。所以它能够控制取值优先级、顺序,并且还提供了访问的方法,后期再想获取也不是问题。

2.使用自定义BeanFactoryPostProcessor

我们自己实现一个自定义BeanFactoryPostProcessor,去除我们不想要显示的属性值的功能来展示自定义BeanFactoryPostProcessor的创建及使用,例如bean定义中我们屏蔽掉‘guapi’、‘shazi’。



    
        
            
                guapi
                shazi
            
        
    

    
        
        
        
    

public class SimpleBean {

   private String userName;
   private String email;
   private String address;
        //getter  setter
}
public class ObscenityRemovingBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

   private final Set obscenities;

   public ObscenityRemovingBeanFactoryPostProcessor() {
      this.obscenities = new HashSet<>();
   }

   /**
    * 将所有bean 的参数中含有 obscenities 集合中的值进行屏蔽
    */
   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      String[] beanNames = beanFactory.getBeanDefinitionNames();
      for (String beanName : beanNames) {
         final BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
         StringValueResolver valueResolver = strVal -> {
            if (isObscene(strVal)){
               return  "*****";
            }
            return strVal;
         };
         final BeanDefinitionVisitor beanDefinitionVisitor = new BeanDefinitionVisitor(valueResolver);
         beanDefinitionVisitor.visitBeanDefinition(beanDefinition);
      }
   }

   public boolean isObscene(Object value){
      String potentialObscenity = value.toString().toUpperCase();
      return this.obscenities.contains(potentialObscenity);
   }

   public void setObscenities(Set obscenities){
      this.obscenities.clear();
      for (String obscenity : obscenities) {
         this.obscenities.add(obscenity.toUpperCase());
      }
   }

}

启动类:

public class Test {

   public static void main(String[] args) {
      ApplicationContext ac = new ClassPathXmlApplicationContext("beanFactory.xml");
      SimpleBean simpleBean = (SimpleBean) ac.getBean("simpleBean");
      System.out.println(simpleBean);
   }
}

输出结果:

SimpleBean{userName='jack', email='*****', address='*****'}

我们通过ObscenityRemovingBeanFactoryPostProcessor我们很好的屏蔽掉了我们不想要显示的属性。

激活BeanFactoryPostProcessor

我们在了解了BeanFactoryPostProcessor的用法之后就可以继续回到我们的refresh方法中继续研究源码了。

进入invokeBeanFactoryPostProcessors方法中。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

   // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
   // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
   if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
      beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
      beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
   }
}

我们继续进入具体重载方法中invokeBeanFactoryPostProcessors。

public static void invokeBeanFactoryPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

   // 将已经执行过的BeanFactoryPostProcessor存储在processedBeans,防止重复执行
   Set processedBeans = new HashSet<>();
   //对BeanDefinitionRegistry类型进行处理
   if (beanFactory instanceof BeanDefinitionRegistry) {
      BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
      // 用来存放BeanFactoryPostProcessor对象
      List regularPostProcessors = new ArrayList<>();
      // 用来存放BeanDefinitionRegistryPostProcessor对象
      // 方便统一执行实现了BeanDefinitionRegistryPostProcessor接口父类的方法
      List registryProcessors = new ArrayList<>();
      // 处理外部定义的BeanFactoryPostProcessor,将BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor区分开
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
         if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
            BeanDefinitionRegistryPostProcessor registryProcessor =
                  (BeanDefinitionRegistryPostProcessor) postProcessor;
            //对于BeanDefinitionRegistryPostProcessor类型,需要先调用此方法,再添加到集合中
            registryProcessor.postProcessBeanDefinitionRegistry(registry);
            registryProcessors.add(registryProcessor);
         } else {
            //记录常规BeanFactoryPostProcessor
            regularPostProcessors.add(postProcessor);
         }
      }

      //存放当前需要执行的BeanDefinitionRegistryPostProcessor
      List currentRegistryProcessors = new ArrayList<>();

      // 调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor。
      // 获取所有实现了BeanDefinitionRegistryPostProcessor接口的类名
      String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
      for (String ppName : postProcessorNames) {
         //判断当前类是否实现了PriorityOrdered接口
         if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            //将BeanDefinitionRegistryPostProcessor类型存入currentRegistryProcessors中
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            // 提前存放到processedBeans,避免重复执行,但是此处还未执行
            processedBeans.add(ppName);
         }
      }
      //对currentRegistryProcessors集合中的BeanDefinitionRegistryPostProcessor类型进行排序
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      // 添加到registryProcessors集合,用于后续执行父接口的postProcessBeanFactory方法
      registryProcessors.addAll(currentRegistryProcessors);
      // 遍历集合,执行BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      //执行完毕后清空该集合
      currentRegistryProcessors.clear();

      // 接着,调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors
      // 这里再次获取BeanDefinitionRegistryPostProcessor,是因为有可能在上面方法执行过程中添加了BeanDefinitionRegistryPostProcessor
      // 而下面处理BeanFactoryPostProcessor的时候又不需要重复获取了是为什么呢?
      // 因为添加BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor只能在BeanDefinitionRegistryPostProcessor中添加,在BeanFactoryPostProcessor是无法添加的
      for (String ppName : postProcessorNames) {
         // 判断当前bean没有被执行过,并且实现了Ordered接口
         if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
            //如果BeanFactory中没有该Bean则会去创建该Bean
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
            processedBeans.add(ppName);
         }
      }
      sortPostProcessors(currentRegistryProcessors, beanFactory);
      registryProcessors.addAll(currentRegistryProcessors);
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();

      //最后处理没有实现Ordered与PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
      boolean reiterate = true;
      while (reiterate) {
         reiterate = false;
         // 再次获取BeanDefinitionRegistryPostProcessor
         postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
         for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName)) {
               // 将本次要执行的BeanDefinitionRegistryPostProcessor存放到currentRegistryProcessors
               currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
               processedBeans.add(ppName);
               reiterate = true;
            }
         }
         sortPostProcessors(currentRegistryProcessors, beanFactory);
         registryProcessors.addAll(currentRegistryProcessors);
         invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
         currentRegistryProcessors.clear();
      }

      //现在,调用到目前为止处理的所有处理器的 postProcessBeanFactory 回调。
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
      invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
   } else {
      // BeanFactory如果不归属于BeanDefinitionRegistry类型,则直接执行beanFactoryPostProcessor
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
   }

   String[] postProcessorNames =
         beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

   // 用于存放实现了priorityOrdered接口的BeanFactoryPostProcessor
   List priorityOrderedPostProcessors = new ArrayList<>();
   // 用于存放实现了ordered接口的BeanFactoryPostProcessor名称
   List orderedPostProcessorNames = new ArrayList<>();
   // 用于存放无排序的BeanFactoryPostProcessor名称
   List nonOrderedPostProcessorNames = new ArrayList<>();
   for (String ppName : postProcessorNames) {
      // 如果已经执行过了,则不做处理
      if (processedBeans.contains(ppName)) {
         // skip - already processed in first phase above
      }
      // 如果实现了PriorityOrdered 则添加
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
         priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
      }
      // 如果实现了Ordered 则添加
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
         orderedPostProcessorNames.add(ppName);
      }
      //如果没有排序则添加到指定集合
      else {
         nonOrderedPostProcessorNames.add(ppName);
      }
   }

   // 首先调用实现 PriorityOrdered 的 BeanFactoryPostProcessor。
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

   // 然后调用实现 Ordered 的 BeanFactoryPostProcessors。
   List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String postProcessorName : orderedPostProcessorNames) {
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   sortPostProcessors(orderedPostProcessors, beanFactory);
   invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

   // 最后调用其他没有排序的 BeanFactoryPostProcessor。
   List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   for (String postProcessorName : nonOrderedPostProcessorNames) {
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
   }
   invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

   // 清空缓存
   beanFactory.clearMetadataCache();
}

注册BeanPostProcessor

了解了BeanFactoryPostProcessors的调用后,我们现在来了解下BeanPostProcessor,这里仅仅是注册,并不是调用。真正的调用在bean实例化阶段进行的。

在BeanFactory中并没有实现后处理器的自动注册功能,所以在调用的时候如果没有进行主动注册则是不能够使用的。但是在ApplicationContext中添加了主动注册功能。

比如自定义这样的后处理器:

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

   @Override
   public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
      System.out.println("===");
      return null;
   }
}

在使用ApplicationContext方式获取bean的时候会在获取之前打印出“===”,在BeanFactory方式进行bean的加载是不会有该打印的。

这个特性就是在registerBeanPostProcessors中实现的。

public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   //获取所有实现BeanPostProcessor接口的类
   String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

   //注册一个 BeanPostProcessorChecker,用来记录 bean 在 BeanPostProcessor 实例化时的信息
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

   //区分实现不同接口的 BeanPostProcessors
   List priorityOrderedPostProcessors = new ArrayList<>();
   List internalPostProcessors = new ArrayList<>();
   List orderedPostProcessorNames = new ArrayList<>();
   List nonOrderedPostProcessorNames = new ArrayList<>();
   //根据不同类型进行add
   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);
      }
   }

   // 排序后执行注册实现了 PriorityOrdered 的 BeanPostProcessors
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

   //注册实现Ordered接口的BeanPostProcessors
   List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   for (String ppName : orderedPostProcessorNames) {
      //拿到ppName对应的BeanPostProcessor实例对象
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      //将ppName对应的BeanPostProcessor实例对象添加到orderedPostProcessors, 准备执行注册
      orderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
         //如果ppName对应的bean实例也实现了MergedBeanDefinitionPostProcessor接口,则添加到该集合中
         internalPostProcessors.add(pp);
      }
   }
   //对orderedPostProcessors进行排序并注册
   sortPostProcessors(orderedPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);

   //注册所有常规的BeanPostProcessors,过程同上
   List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   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,并非重复注册
   //在beanFactory.addBeanPostProcessor中会先移除已经存在的BeanPostProcessor
   sortPostProcessors(internalPostProcessors, beanFactory);
   registerBeanPostProcessors(beanFactory, internalPostProcessors);

   // 添加ApplicationListener探测器
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

初始化消息资源

在initMessageSource中主要功能是提取配置文件中的messageSource,并将其记录在Spring容器中,也就是ApplicationContext中。如果用户未设置资源文件的话,则获取Spring默认的配置delegatingMessageSource。

protected void initMessageSource() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   // Bean 的名称必须要是 messageSource
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { //MESSAGE_SOURCE_BEAN_NAME = messageSource
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      // Make MessageSource aware of parent MessageSource.
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            // Only set parent context as parent MessageSource if no parent MessageSource
            // registered already.
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
      if (logger.isTraceEnabled()) {
         logger.trace("Using MessageSource [" + this.messageSource + "]");
      }
   }
   else {
      //如果用户并没有定义配置文件,那么使用临时的DelegatingMessageSource以便于作为调用getMessage的返回
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
      }
   }
}

这里规定资源文件必须为messageSource,否则就会获取不到自定义资源配置。

初始化ApplicationEventMulticaster

initApplicationEventMulticaster方法实现比较简单,存在两种情况:

protected void initApplicationEventMulticaster() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //判断容器中是否存在BeanDefinitionName为applicationEventMulticaster的bd,也就是自定义的事件监听多路广播器,必须实现ApplicationEventMulticaster接口
   if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
   }
   else {
      //如果没有,则默认采用SimpleApplicationEventMulticaster
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
               "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
      }
   }
}

最后,作为广播器,一定是用于存放监听器并在合适的时候调用监听器,我们进入默认的广播器实现类SimpleApplicationEventMulticaster中看一下。

看到如下方法:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}

可以推断,当产生Spring事件的时候会默认使用SimpleApplicationEventMulticaster的multicastEvent来广播事件,遍历所有监听器,并使用监听器中的onApplicationEvent方法来进行监听器的处理。而对于每个监听器来说其实都可以获取到产生的事件,但是是否进行处理则由事件监听器决定。

注册监听器

我们反复提到了监听器,我们接下来看一下Spring注册监听器的时候又做了哪些逻辑操作?

protected void registerListeners() {
   // 首先注册静态的指定的监听器,注册的是特殊的事件监听器,而不是配置中的bean
   for (ApplicationListener<?> listener : getApplicationListeners()) {
      getApplicationEventMulticaster().addApplicationListener(listener);
   }

   // 这里不会初始化FactoryBean,我们需要保留所有的普通bean
   // 不会实例化这些bean,让后置处理器可以感知到它们
   String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
   for (String listenerBeanName : listenerBeanNames) {
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
   }

   // 现在有了事件广播组,发布之前的应用事件
   Set earlyEventsToProcess = this.earlyApplicationEvents;
   this.earlyApplicationEvents = null;
   if (earlyEventsToProcess != null) {
      for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
         getApplicationEventMulticaster().multicastEvent(earlyEvent);
      }
   }
}

只是将一些特殊的监听器注册到广播组中,那些在bean配置文件中实现了ApplicationListener接口的类还没有实例化,所以此时只是将name保存到了广播组中,将这些监听器注册到广播组中的操作时在bean的后置处理器中完成的,那时候bean的实例化已经完成了。

初始化非延迟加载单例

完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
   // 初始化此上下文的转换服务
   if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
         beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
      beanFactory.setConversionService(
            beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
   }

   // 如果beanFactory之前没有注册解析器,则注册默认的解析器,例如${}解析成真正的属性:主要用于注解属性值的解析
   if (!beanFactory.hasEmbeddedValueResolver()) {
      beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
   }

   //处理 @EnableLoadTimeWeaving 或   标记的类
   String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
   for (String weaverAwareName : weaverAwareNames) {
      getBean(weaverAwareName);
   }

   //临时类加载器设置为空
   beanFactory.setTempClassLoader(null);

   //冻结所有的bean定义,说明注册的bean定义将不被修改或者进一步处理
   beanFactory.freezeConfiguration();

   //初始化剩下的单例实例(非惰性)
   beanFactory.preInstantiateSingletons();
}

首先,我们先了解下ConversionService类所提供的作用。

1.ConversionService的设置

之前我们提到可以用自定义类型转换器把String类型转换为Date,在Spring中也提供了使用Converter来进行转换。

2.冻结配置

冻结所有的bean定义,说明注册的bean定义将不被修改或者进行任何一步的处理。

public void freezeConfiguration() {
   this.configurationFrozen = true;
   this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
}

3.初始化延迟加载

ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化。提前实例化也就意味着作为初始化过程的一部分,ApplicationContext实例会创建并配置所有单例bean,这个实例化过程就是在finishBeanFactoryInitialization方法中的preInstantiateSingletons方法中完成的。

public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   //创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义
   List beanNames = new ArrayList<>(this.beanDefinitionNames);

   //遍历beanNames,触发所有非懒加载单例bean的初始化
   for (String beanName : beanNames) {
      //获取beanName对应的MergedBeanDefinition
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //bd对应的不是抽象类 && 并且是单例 && 并且不是懒加载
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         //判断是否为FactoryBean
         if (isFactoryBean(beanName)) {
            //通过前缀&和beanName拿到Bean
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            //如果为FactoryBean
            if (bean instanceof FactoryBean) {
               final FactoryBean<?> factory = (FactoryBean<?>) bean;
               //判断这个FactoryBean是否希望急切的初始化
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged((PrivilegedAction)
                              ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               //如果希望急切的初始化,则通过beanName获取bean实例
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            //如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
            getBean(beanName);
         }
      }
   }

   //遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
   for (String beanName : beanNames) {
      //拿到beanName对应的bean实例
      Object singletonInstance = getSingleton(beanName);
      //判断singletonInstance是否实现了SmartInitializingSingleton接口
      if (singletonInstance instanceof SmartInitializingSingleton) {
         final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         //触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction) () -> {
               smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}

finishRefresh

在Spring中提供了Lifecycle接口,该接口包含start/stop方法,实现此接口后Spring会保证在启动时候调用其start方法开始声明周期,并在Spring关闭时候调用stop方法来结束声明周期。通常用来配置后台程序,在启动后一直运行(比如MQ)而ApplicationContext最后一步finishRefresh方法就是实现这一功能。

protected void finishRefresh() {
   //清除资源缓存
   clearResourceCaches();

   //1.为此上下文初始化生命周期处理器
   initLifecycleProcessor();

   //2.首先将刷新完毕事件传播到生命周期处理器(触发isAutoStartup方法返回true的SmartLifecycle的start方法)
   getLifecycleProcessor().onRefresh();

   //3.推送上下文刷新完毕事件到相应的监听器
   publishEvent(new ContextRefreshedEvent(this));

   // Participate in LiveBeansView MBean, if active.
   LiveBeansView.registerApplicationContext(this);
}

1.initLifecycleProcessor

当ApplicationContext启动或停止时,它会通过LifecycleProcessor来和所有声明的bean的周期做状态更新,而在LifecycleProcessor的使用前首先进行初始化。

protected void initLifecycleProcessor() {
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //判断BeanFactory是否已经存在生命周期处理器(beanName=lifecycleProcessor)
   if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
      this.lifecycleProcessor =
            beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
      if (logger.isTraceEnabled()) {
         logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
      }
   }
   else {
      //如果不存在,则使用DefaultLifecycleProcessor
      DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
      defaultProcessor.setBeanFactory(beanFactory);
      this.lifecycleProcessor = defaultProcessor;
      // 并将DefaultLifecycleProcessor作为默认的生命周期处理器,注册到BeanFactory中
      beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
               "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
      }
   }
}

2.onRefresh

启动所有实现了Lifecycle接口的bean

public void onRefresh() {
   startBeans(true);
   this.running = true;
}
private void startBeans(boolean autoStartupOnly) {
   Map lifecycleBeans = getLifecycleBeans();
   Map phases = new HashMap<>();
   lifecycleBeans.forEach((beanName, bean) -> {
      if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
         int phase = getPhase(bean);
         LifecycleGroup group = phases.get(phase);
         if (group == null) {
            group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
            phases.put(phase, group);
         }
         group.add(beanName, bean);
      }
   });
   if (!phases.isEmpty()) {
      List keys = new ArrayList<>(phases.keySet());
      Collections.sort(keys);
      for (Integer key : keys) {
         phases.get(key).start();
      }
   }
}

3.publishEvent

当完成ApplicationContext初始化的时候,要通过Spring中的发布机制来发出ContextRefreshedEvent事件,以保证对应的监听器可以做进一步的逻辑处理。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
   Assert.notNull(event, "Event must not be null");

   //如有必要,将事件装饰为ApplicationEvent
   ApplicationEvent applicationEvent;
   if (event instanceof ApplicationEvent) {
      applicationEvent = (ApplicationEvent) event;
   }
   else {
      applicationEvent = new PayloadApplicationEvent<>(this, event);
      if (eventType == null) {
         eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
      }
   }

   // Multicast right now if possible - or lazily once the multicaster is initialized
   if (this.earlyApplicationEvents != null) {
      this.earlyApplicationEvents.add(applicationEvent);
   }
   else {
      //使用事件广播器广播事件到相应的监听器
      getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
   }

   //通过parent发布事件
   if (this.parent != null) {
      if (this.parent instanceof AbstractApplicationContext) {
         ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
      }
      else {
         this.parent.publishEvent(event);
      }
   }
}

到这里,refresh方法就解析完成了。下一步就是AOP了。


如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,

咱们下期见!答案获取方式:已赞 已评 已关~

学习更多JAVA知识与技巧,关注与私信博主(03)


Spring源码之容器的功能扩展和refresh方法解析



















原文出处:https://segmentfault.com/a/1190000041999221

页面更新:2024-04-23

标签:功能   方法   监听器   遍历   初始化   容器   处理器   源码   实例   加载   接口   事件

1 2 3 4 5

上滑加载更多 ↓
Top