Spring启动流程[5]刷新上下文[2]前置处理

378 阅读4分钟

这里对应的是AbstractApplicationContext中以下部分的代码:

 try {
    // Allows post-processing of the bean factory in context subclasses.
    postProcessBeanFactory(beanFactory);
 ​
    StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    // Invoke factory processors registered as beans in the context.
    invokeBeanFactoryPostProcessors(beanFactory);
 ​
    // Register bean processors that intercept bean creation.
    registerBeanPostProcessors(beanFactory);
    beanPostProcess.end();

一行一行来看。

postProcessBeanFactory

这部分其实是抽象类预留的钩子接口,在run方法中用到的是如下代码(AnnotationConfigServletWebServerApplicationContext):

 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    super.postProcessBeanFactory(beanFactory);
    if (!ObjectUtils.isEmpty(this.basePackages)) {
       this.scanner.scan(this.basePackages);
    }
    if (!this.annotatedClasses.isEmpty()) {
       this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
    }
 }

super的代码如下(GenericWebApplicationContext):

 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    if (this.servletContext != null) {
       beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
       beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    }
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
 }

这里也是注册和忽略一些接口。

后面两行的作用,是:

  • 在beanFactory中注册一些和scope相关的内容。
  • 在beanFactory中,注册环境bean。

调用beanFactory的前置处理

接下来就是开一个startupStep,然后

 invokeBeanFactoryPostProcessors(beanFactory);
 ​
     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 (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
         }
     }

这里流程里的代码也比较理解,其实就是设置了一些参数。主要来看看这个:

 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

这个方法里代码比较多,分步来看:

1.如果类继承了BeanDefinitionRegistry

这里对应的代码如下:

 if (beanFactory instanceof BeanDefinitionRegistry) {
 //......
 }

一样分步来看:

1.1 归类postProcessor

 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
       BeanDefinitionRegistryPostProcessor registryProcessor =
             (BeanDefinitionRegistryPostProcessor) postProcessor;
       registryProcessor.postProcessBeanDefinitionRegistry(registry);
       registryProcessors.add(registryProcessor);
    }
    else {
       regularPostProcessors.add(postProcessor);
    }
 }

请注意:这里会调用registryProcessor的处理并放入registryProcessor

这里会将postProcessor归为两类:

  • registryProcessor
  • regularPostProcessor

这里的registryProcessor,其实是postProcessor的一个扩展,此处的注册节点是在普通的postProcessor之前的,当然也能注册一些定义postProcessor的一些bean定义。

1.2 分类并调用registryProcessor

这里会将BDRegistry分为三类:

  •  PriorityOrdered, Ordered, and the rest.
    
  • 这里需要注意:注释里提到了此处并不会初始化facotryBean
1.2.1 priorityOrder

简言之,这里就是先将这些继承了priorityOrder的processor取出来,后续一次性都调用。

 // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
 String[] postProcessorNames =
       beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
 for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
       currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
       processedBeans.add(ppName);
    }
 }
 sortPostProcessors(currentRegistryProcessors, beanFactory);
 registryProcessors.addAll(currentRegistryProcessors);
 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
1.2.2 ordered

这里跟上面相同,就是变成了order的。

需要注意:

  • 这里重新获得了一次postProcessorNames,因为在上一步可能发生了对beanFactory这部分内容的修改。
  • 方法内存了processedBeans,每次初始化加入的时候判断了,这样就不会重复加入了。
 // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
 for (String ppName : postProcessorNames) {
    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
       currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
       processedBeans.add(ppName);
    }
 }
 sortPostProcessors(currentRegistryProcessors, beanFactory);
 registryProcessors.addAll(currentRegistryProcessors);
 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
 currentRegistryProcessors.clear();
1.2.3 other

这里就是所说的其他的了。

 boolean reiterate = true;
 while (reiterate) {
    reiterate = false;
    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    for (String ppName : postProcessorNames) {
       if (!processedBeans.contains(ppName)) {
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
          processedBeans.add(ppName);
          reiterate = true;
       }
    }
    sortPostProcessors(currentRegistryProcessors, beanFactory);
    registryProcessors.addAll(currentRegistryProcessors);
    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    currentRegistryProcessors.clear();
 }

1.3 调用所有的postProcessor

到这一步,BDRegistryProcessor都被初始化分类执行完了,接下来就是跟1.1里的regular一起处理了:

 // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

在这一步,registryPostProcessor就跟普通的postProcessor一样,调用其postProcessBeanFactory方法了。

2.如果不继承

按照流程,其实是我们输入的是继承了BDRegistry的,那么如果不继承呢?

其实就直接执行这个方法了:

 else {
    // Invoke factory processors registered with the context instance.
    invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
 }

也就是说:不拿这个beanFactoryPostProcessors来作为registryPostProcessor折腾了,也不管前后顺序了,直接作为postProcessor一把梭了。

3.按照优先级处理postProcessor

这里需要注意:

  • 前面的所有实际上执行的postProcessor,都是传进来的参数,1里面处理的实际上都是BeanDefinitionRegistryPostProcessor。

所以接下来就是来处理beanFactory的那些postProcessor了,这部分的流程和1类似,这里只说一下不同点:

  • 这里和1不同,先分类再统一执行。
  • 最后会执行:beanFactory.clearMetadataCache();

注册beanFactory的前置处理

接下来就是注册了:

 // Register bean processors that intercept bean creation.
                 registerBeanPostProcessors(beanFactory);
                 beanPostProcess.end();

主要来看看这个:

     protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
         PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
     }

这个方法里代码比较多,其实是里面干的事情总结一下就是:

  • 找postProcessor:

     String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
    
  • 分别处理

1.注册检查器

这里注册了一个beanPostProcessor BeanPostProcessorChecker,不知道是啥也没关系,注解写得很清楚了:这个postProcessor就是用来在beanPostProcessor实例化时,如果有bean被创建了就打印日志的。

 // Register BeanPostProcessorChecker that logs an info message when
 // a bean is created during BeanPostProcessor instantiation, i.e. when
 // a bean is not eligible for getting processed by all BeanPostProcessors.
 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
 beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

2.分类postProcessor并注册

跟1的前置处理类似,这里就是按照顺序标记的进行分类,并逐一重新按顺序添加到beanFactory里面。

最后,添加了一个新的postProcesor:

 new ApplicationListenerDetector(applicationContext)

这个postProcessor的目的,是检测像ApplicationListener这种内部类的。

总结

简单地说:这部分地内容就是拿着ApplicationContext里的postProcessor,对BF的处理。

到这里,我们知道了两个Spring中支持扩展的点:

  • BeanDefinitionRegistryPostProcessor
  • BeanPostProcessor

上面这个BeanDefinitionRegistryPostProcessor的调用,会先于postProcessor

  • 特殊处理的前提是BeanFactory继承了BeanRegistry
  • 如果没有的话,上面的就不会特殊处理了,只会先一步调用。