美文网首页
4-BeanFactory的增强:ApplicationCont

4-BeanFactory的增强:ApplicationCont

作者: 鹏程1995 | 来源:发表于2020-02-25 16:12 被阅读0次

概要

过度

上面我们宏观介绍了refresh()的基本思路:

1.png

接下来我们按照框出来的四个部分依次介绍,本节介绍的是BeanFactory的处理及设置。

内容简介

本节介绍的是BeanFactory的一些加载以及设置,包括:

  1. BeanFactory的创建及BD加载、注册
  2. BeanFactory一些实例化策略字段的设置
  3. BeanFactory对一些后处理操作
  4. BeanFactory后处理器的配置

所属环节

BeanFactory的加载及设置。

上下环节

上文: 完成刷新前的标记量设置和环境验证

下文: 根据硬编码和BeanFactory中的配置,对ApplicationContext进行设置

源码解析

入口

public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
    // Prepare this context for refreshing.
    // 准备此 ApplicationContext
    prepareRefresh();

    // Tell the subclass to refresh the internal bean factory.
    // BeanFactory 的初始化及对应的 BD 的加载
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    // Prepare the bean factory for use in this context.
    // 对 BeanFactory 中的一些和上下文相关的属性进行设置和同步。
    prepareBeanFactory(beanFactory);

    try {
      // Allows post-processing of the bean factory in context subclasses.
      // 定义了一个钩子,供子类实现
      postProcessBeanFactory(beanFactory);

      // Invoke factory processors registered as beans in the context.
      // 调用 BeanFactory 的后处理器对其进行处理
      invokeBeanFactoryPostProcessors(beanFactory);

      // Register bean processors that intercept bean creation.
      // 注册那些拦截 Bean 创建的后处理器
      // 注意,上面 invokeBeanFactoryPostProcessors() 各种实例化各种注册,操作的都是针对 factory 的后处理器。这里才是针对 bean
      // 的后处理器
      registerBeanPostProcessors(beanFactory);

      // Initialize message source for this context.
      // 初始化本 context 的 Message 源【国际化和本土化】【将对应的信息符号转化成对应的语言提示】
      // TODO 没啥需要,最后再看
      initMessageSource();

      // Initialize event multicaster for this context.
      // 初始化事件广播相关的东西
      initApplicationEventMulticaster();

      // Initialize other special beans in specific context subclasses.
      // 子实现类根据各自情况实现其他的特殊 Bean 的处理
      // 算是留下的一个钩子
      onRefresh();

      // Check for listener beans and register them.
      // 找出所有可注册的监听器并注册成有效的监听器,完成初始化后将之前缓存的事件散发出去
      registerListeners();

      // Instantiate all remaining (non-lazy-init) singletons.
      // 将剩余的非懒加载的单例加载一下
      finishBeanFactoryInitialization(beanFactory);

      // Last step: publish corresponding event.
      // 完成启动,散发相应事件
      finishRefresh();
    } catch (BeansException ex) {
      if (logger.isWarnEnabled()) {
        logger.warn("Exception encountered during context initialization - " +
                    "cancelling refresh attempt: " + ex);
      }

      // Destroy already created singletons to avoid dangling resources.
      destroyBeans();

      // Reset 'active' flag.
      cancelRefresh(ex);

      // Propagate exception to caller.
      throw ex;
    } finally {
      // Reset common introspection caches in Spring's core, since we
      // might not ever need metadata for singleton beans anymore...
      resetCommonCaches();
    }
  }
}

上面是我们在总览中提到的整体的思路。我们本节要介绍的是以下几句:

  • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  • prepareBeanFactory(beanFactory);
  • postProcessBeanFactory(beanFactory);
  • invokeBeanFactoryPostProcessors(beanFactory);
  • registerBeanPostProcessors(beanFactory);

BeanFactory的初始化及BD的注册

此阶段对应的代码行是ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();代码展示如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  // 初始化 BeanFactory 并进行文件读取,并将处理完成的 BeanFactory 放到本 context 中
  // 本类只关注整体的 context 流程,具体用什么 BeanFactory ,如何操作,由子类自行定制
  refreshBeanFactory();

  // 获得保存在本 context 中的 BeanFactory
  ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  if (logger.isDebugEnabled()) {
    logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
  }
  return beanFactory;
}

protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

其中,我们例子中使用的是ClassPathXmlApplicationContext,该类j继承于AbstractRefreshableApplicationContext即可重复刷新的ApplicationContext,它的相关实现为:

// 清除之前的 BeanFactory , 然后重新设置、加载 BeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
  if (hasBeanFactory()) {
    destroyBeans();
    closeBeanFactory();
  }
  try {
    // 创建 DefaultListableBeanFactory
    DefaultListableBeanFactory beanFactory = createBeanFactory();
    // 这个是 DefaultListableBeanFactory 设置的全局缓存。使用弱引用,不会影响垃圾回首你,
    // 后面有需要可以直接通过 id 得到对应的 BeanFactory 实例。
    beanFactory.setSerializationId(getId());

    // TODO 看看从哪增加的对 Autowired 之类的注解的支持
    // 根据 context 的设置定制 BeanFactory 的属性
    customizeBeanFactory(beanFactory);
    // 从配置文件【或者其他的配置载体】加载 BD 并完成注册
    loadBeanDefinitions(beanFactory);
    // 保存此次加载的结果
    synchronized (this.beanFactoryMonitor) {
      this.beanFactory = beanFactory;
    }
  } catch (IOException ex) {
    throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
  }
}

其中,定制BeanFactory的函数customizeBeanFactory()主要是对BeanFactory的一些实现策略进行定制:

// 定制 context 中的 BeanFactory
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
  if (this.allowBeanDefinitionOverriding != null) {
    // 允许 BD 的同名覆盖
    beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  }
  if (this.allowCircularReferences != null) {
    // 允许循环依赖
    beanFactory.setAllowCircularReferences(this.allowCircularReferences);
  }
}

由于AbstractRefreshableApplicationContext只是关注可重复加载的特性。并不关注是从哪进行加载。所以我们从XmlWebApplicationContext中找到loadBeanDefinitions()的实现方式:

// 从 XML 文件中加载 BD ,并完成注册
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
  // Create a new XmlBeanDefinitionReader for the given BeanFactory.
  XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

  // Configure the bean definition reader with this context's
  // resource loading environment.
  beanDefinitionReader.setEnvironment(getEnvironment());
  beanDefinitionReader.setResourceLoader(this);
  beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

  // Allow a subclass to provide custom initialization of the reader,
  // then proceed with actually loading the bean definitions.
  initBeanDefinitionReader(beanDefinitionReader);
  loadBeanDefinitions(beanDefinitionReader);
}

实现的整体思路和之前我们读XmlBeanFactory的构造函数基本一致。除了我们多设置了一个Environment,一个ResourceLoader和一个EntityResolver

其实总结一下这部分的东西,主干还是最后这里的BeanFactory的BD注册。只是我们在这之间做了很多属性设置:比如将环境、资源加载器、资源解析器、BD的注册策略限制的字段等等配置进去了。

BeanFactory的一些实例化策略字段的设置

这里对应了入口的prepareBeanFactory(beanFactory);函数。

// 配置工厂的一些特性,例如把工厂中处理bean、BD的后处理器啥的都注册进去,方便后面调用
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  // Tell the internal bean factory to use the context's class loader etc.
  // 设置一些属性、类加载器、上下文环境啥的东西
  // 类加载器
  beanFactory.setBeanClassLoader(getClassLoader());
  // SpEL 解析器
  // 这个不是我们用 ${} 取环境变量那种了。这个是用 #{} 的,是 Spring 定义的,一个完整
  // 的和 Spring 框架切合的表达式解析体系
  // 【在构造实例的那个 autowireConstructor 那里有使用这个,对配置的 value 为 String 类型的东西进行解析】
  beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  // 对 value 属性进行反序列化解析
  // 可以在这里设置,也可配置成 CustomEditorConfigurer .创建 BD 注册到要添加的 BeanFactory 中
  // context 会自动发现 BeanFactory 中注册成 Bean 的后处理器并完成创建、注册。
  // 【明确目的角色后,使用地点大概也能猜到了吧。。。】
  // 【在进行 Bean 的实例化时,使用的是 BeanWrapper ,在初始化它时会调用将 BeanFactory 中的东西注册给它,后面它设置值时会自动进行合适的调用】
  // 【这个 ResourceEditorRegistrar 应该是资源引用相关的,将对应的资源 url 转换成对应的 Resource】
  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

  // Configure the bean factory with context callbacks.
  // 和 context 上下文相关的东西,通过这个后处理器来完成注入
  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  // 虽然Spring会让用户尽可能灵活,但是不能违背接口的初衷,Aware是用来让框架自己往里丢东西的,不能用来注入
  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 interface not registered as resolvable type in a plain factory.
  // MessageSource registered (and found for autowiring) as a bean.
  // 设置一些和上下文相关的可以注入的类型和要注入的值
  // 这些属性不仅可以通过aware进行获取,也可以直接通过依赖注入进行获取,方便用户灵活使用
  beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  beanFactory.registerResolvableDependency(ApplicationContext.class, this);

  // Register early post-processor for detecting inner beans as ApplicationListeners.
  // 注册一个后处理器,用来检测内部注册的合适的 bean ,并将合适的注册成 ApplicationListeners
  // TODO 这个地方感觉必然会出现问题
  // 因为在启动时就会产生很多事件,在完成事件分发器的初始化就会开始事件消费。但是如果采用后处理器进行监听器的发现和注册,
  // 只有主动触发对应 Bean 的实例化才能进行监听器
  // TODO 这样即使设置成提前加载,也无法完整的获得所有的事件
  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

  // Detect a LoadTimeWeaver and prepare for weaving, if found.
  // TODO 这个应该是和 AOP 代理相关的东西
  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()));
  }

  // Register default environment beans.
  // 设置 BeanFactory 中的环境相关属性
  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的创建和BD的注册进行了操作,并对BD做了一些策略限制。现在我们对BeanFactory中的实例化策略进行配置,包括:

  1. 对资源加载和SpEL的支持
  2. 对上下文参数获取的相关支持
  3. 对一些AOP、环境的设置【其他的小点吧】
  4. 当然还加进去一个ApplicationContext 的监听器的发现器

其中(4)很好理解,就是加了一个后处理器,如果发现要处理的实例化的Bean是监听器类型的,就在上下文中进行注册。(3)我们后面在讲完AOP再回来看。(1)涉及专门的解析器,我们看代码中注释了解其角色职能即可。我们主要关注(2),这里涉及整体的流程:

我们先注册了一个后处理器:ApplicationContextAwareProcessor(),它会根据Bean的Class实现的aware接口将上下文指定的参数设置进去,我们看一下它的逻辑:

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
  AccessControlContext acc = null;

  if (System.getSecurityManager() != null &&
      (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
       bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
       bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
    acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  }

  if (acc != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
      invokeAwareInterfaces(bean);
      return null;
    }, acc);
  } else {
    invokeAwareInterfaces(bean);
  }

  return bean;
}

private void invokeAwareInterfaces(Object bean) {
  if (bean instanceof Aware) {
    if (bean instanceof EnvironmentAware) {
      ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    }
    if (bean instanceof EmbeddedValueResolverAware) {
      ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    }
    if (bean instanceof ResourceLoaderAware) {
      ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    }
    if (bean instanceof ApplicationEventPublisherAware) {
      ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    }
    if (bean instanceof MessageSourceAware) {
      ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    }
    if (bean instanceof ApplicationContextAware) {
      ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    }
  }
}

然后为了方便用户用,ApplicationContextBeanFActory中不仅设置了对aware接口的支持,还将对应的参数通过beanFactory.registerResolvableDependency()进行注册,用户想怎么获得就怎么获得。

当然,aware接口的意义是打一个标,框架会自动将制定属性给你灌进去,不能用来进行依赖注入。这里通过调用beanFactory.ignoreDependencyInterface()对用户进行了限制。

BeanFactory的后处理操作

此部分对应的是我们refresh()中的invokeBeanFactoryPostProcessors(beanFactory);,我们会发现在Spring中,后处理器是一个非常有利的工具,可以对目标进行各种改造,极其方便,根据之前我们对BeanFActory的介绍我们知道了BD和Bean都有后处理器。ApplicationContext也引入了BeanFactory的后处理器。

// 实例化并调用所有注册的后处理器 Bean 。如果定义调用顺序,就按定义的顺序来。
// 必须在单例初始化之前调用

// TODO 常用的 BeanFactory 后处理器有 PropertyPlaceholderConfigurer ,他可以读取指定的 *.properties文件,并
// 遍历 BeanFactory 中的所有 BD ,对其所有相关属性属性进行变量值替换

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  // 调用处理 BeanFactory 的后处理器
  // 这里将上下文中注册的后处理器也穿进去,一起用。
  // 这里先调用穿进去的后处理器,然后会把 BeanFactory 中定义的 BeanFactoryPostProcessor 一起找出来调用
  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)
  // TODO 这里不清楚是干什么的
  if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  }
}

这里将BeanFactory的后处理器的调用委托给了PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(),后面这一步设置TempClassLocader和类似AOP相关的后处理器的设置,这里我是没看懂,看后面如果有需要,这里再回来看吧。

接下来我们继续看一下他是怎么调用的BeanFactory的后处理器的:

// 调用后处理器对 BeanFactory 进行处理
// 入参为额外的后处理器,要对 BeanFactory 进行处理。此函数也要对 BeanFactory 中合适的后处理器类型进行发现并调用
public static void invokeBeanFactoryPostProcessors(
  ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

  // Invoke BeanDefinitionRegistryPostProcessors first, if any.
  Set<String> processedBeans = new HashSet<>();

  // 先调用一下传进来的额外的 BeanFactory 后处理器
  if (beanFactory instanceof BeanDefinitionRegistry) {      // BeanDefinitionRegistry 类型的调用
    BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    // 硬编码的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    // 所有的 BeanDefinitionRegistryPostProcessor
    List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

    // 先把硬编码带进来的后处理器处理了,如果是 BeanDefinitionRegistryPostProcessor 就立即调用
    for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
      if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
        BeanDefinitionRegistryPostProcessor registryProcessor =
          (BeanDefinitionRegistryPostProcessor) postProcessor;
        registryProcessor.postProcessBeanDefinitionRegistry(registry);
        registryProcessors.add(registryProcessor);
      } else {
        regularPostProcessors.add(postProcessor);
      }
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    // Separate between BeanDefinitionRegistryPostProcessors that implement
    // PriorityOrdered, Ordered, and the rest.
    // 这里没有对 BeanFactory 中的普通 bean 进行实例化,这样注册后处理器后能对所有的普通 bean 生效
    List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

    // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    // 从 BeanFactory 中取出所有的 BeanDefinitionRegistryPostProcessor ,并进行调用实现 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);
    currentRegistryProcessors.clear();//注意这里清空了

    // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
    // 从 BeanFactory 中取出所有的 BeanDefinitionRegistryPostProcessor ,并进行调用实现 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);
    currentRegistryProcessors.clear();

    // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    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;
        }
      }
      // 拿到了所有的未调用过的 BeanDefinitionRegistryPostProcessor
      // 这里拿到的应该是未实现 PriorityOrdered,Ordered 的
      sortPostProcessors(currentRegistryProcessors, beanFactory); // 感觉强行排序,后面的 mbd 的这种就没排
      registryProcessors.addAll(currentRegistryProcessors);
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
      currentRegistryProcessors.clear();
    }
    // TODO 到这里,将所有的 BeanDefinitionRegistryPostProcessor 调用完了
    // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    // TODO 这里没有重复调用问题,原因自己想
        // 此处不存在重复调用的低效问题,这两种后处理器不一样,BeanDefinitionRegistryPostProcessor 有两个方法可以调用

    invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    // 把没调用过的 BeanFactoryPostProcessor 调用一遍
    invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
  } else {
    // BeanFactoryPostProcessor 类型的调用
    // 这里只调用了入参的那些,这是硬编码写死的。还得从注册的 bean 里看有没有漏掉的
    // Invoke factory processors registered with the context instance.
    invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
  }

  // 到这里,我们把传进来的额外的后处理器调用完了,现在从 BeanFactory 中找找看有没有注册的还能调用的
  // Do not initialize FactoryBeans here: We need to leave all regular beans
  // uninitialized to let the bean factory post-processors apply to them!
  String[] postProcessorNames =
    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

  // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
  // Ordered, and the rest.

  // TODO 和下面对 MBD 的处理一个套路【只是这里是调用,不是注册】,看是不是可以抽离使用模版方法进行简化和统一
  // TODO 上面的 BeanDefinitionRegistry 不晓得有没有什么特殊之处,看是不是也能统一
  List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
  List<String> orderedPostProcessorNames = new ArrayList<>();
  List<String> nonOrderedPostProcessorNames = new ArrayList<>();
  for (String ppName : postProcessorNames) {
    if (processedBeans.contains(ppName)) {
      // skip - already processed in first phase above
    } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
      priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
      orderedPostProcessorNames.add(ppName);
    } else {
      nonOrderedPostProcessorNames.add(ppName);
    }
  }

  // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
  sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
  invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

  // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
  List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
  for (String postProcessorName : orderedPostProcessorNames) {
    orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  }
  sortPostProcessors(orderedPostProcessors, beanFactory);
  invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

  // Finally, invoke all other BeanFactoryPostProcessors.
  List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
  for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
  }
  invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

  // Clear cached merged bean definitions since the post-processors might have
  // modified the original metadata, e.g. replacing placeholders in values...
  beanFactory.clearMetadataCache();
}

代码中的注释能帮助我们解决大部分的问题,这里对整个函数的思路进行一个梳理,首先,我们先自己想一下如果我们自己写的话,我们会怎么写——我们知道,BeanFactory的后处理器这里分成了两类,我们通过阅读两个后处理的Class文件定义得知:

BeanFactoryPostProcessor:对BeanFactory的后处理器,可以在BeanFactory初始化完成后修改其中的BD,或者其他的东西

BeanDefinitionRegistryPostProcessor:扩展了上面的接口,可以进行上面的后处理器的BD的注册,上下文会自动发现你新增的上面的后处理器的注册,并进行实例化和调用。这类后处理器会在上面的处理器之前调用以保证修改对上面的后处理器调用可见

同时,我们要调用的后处理器有两个来源:

  1. 配置在context中的,通过入参带进来
  2. 你在BeanFactory中配置的,需要进行发现,并将符合条件BD的进行实例化,然后调用

所以我们大概一猜测,思路应该是这样的:

2.png

我们对代码进行阅读,发现了两个出入:

  1. 源码中对BeanDefinitionRegistryPostProcessor的实现是保证它的两个钩子都在纯粹的BeanFactoryPostProcessor之前调用。
  2. 所有的BeanFactoryPostProcessor的钩子的调用都根据实现的优先级接口进行了排序。

我们对上面的流程图进行修改:

3.png

基本这就是上面的函数的思路了。

BeanFactory的后处理器注册

这里是对refresh()中的registerBeanPostProcessors()的详细解读。这部分的主要作用是发现在BeanFactory中注册的用来处理BD、Bean的后处理器,并进行实例化,然后注册到BeanFactory中,方便后面在使用时这些后处理器能发挥作用。这个就没啥思路可说了,直接上代码:

/**
     * Instantiate and register all BeanPostProcessor beans,
     * respecting explicit order if given.
     * <p>Must be called before any instantiation of application beans.
     */
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
  PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
public static void registerBeanPostProcessors(
  ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

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

  // 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));

  // Separate between BeanPostProcessors that implement PriorityOrdered,
  // Ordered, and the rest.
  List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
  List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
  List<String> orderedPostProcessorNames = new ArrayList<>();
  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) { // mbd 的后处理器缓存起来
        internalPostProcessors.add(pp);
      }
    } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
      orderedPostProcessorNames.add(ppName);
    } else {
      nonOrderedPostProcessorNames.add(ppName);
    }
  }

  // First, register the BeanPostProcessors that implement PriorityOrdered.
  // 注册所有实现 PriorityOrdered 的
  sortPostProcessors(priorityOrderedPostProcessors, beanFactory); // 对实现优先级的列表进行排序
  registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // 排序之后按照顺序完成注册

  // Next, register the BeanPostProcessors that implement Ordered.
  // 注册所有实现 Ordered 的
  List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
  for (String ppName : orderedPostProcessorNames) {
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    orderedPostProcessors.add(pp);
    if (pp instanceof MergedBeanDefinitionPostProcessor) { // mbd 的后处理器缓存起来
      internalPostProcessors.add(pp);
    }
  }
  // 一个套路,排序、注册
  sortPostProcessors(orderedPostProcessors, beanFactory);
  registerBeanPostProcessors(beanFactory, orderedPostProcessors);

  // Now, register all regular BeanPostProcessors.
  // 注册普通的
  List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
  for (String ppName : nonOrderedPostProcessorNames) {
    BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    nonOrderedPostProcessors.add(pp);
    if (pp instanceof MergedBeanDefinitionPostProcessor) {// mbd 的后处理器缓存起来
      internalPostProcessors.add(pp);
    }
  }
  // 不需要排序了,直接注册
  registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

  // Finally, re-register all internal BeanPostProcessors.
  // mbd 的后处理器再次进行注册
  // 这里存在后处理器的重复注册问题,所有的 mbd 的后处理器都注册了两次。进去看会发现,底层进行了去重操作,【移除了旧的】
  // TODO 上层代码这么搞可能是为了逻辑清晰吧,毕竟按这种写法后面可以抽离成子函数
  sortPostProcessors(internalPostProcessors, beanFactory);
  registerBeanPostProcessors(beanFactory, internalPostProcessors);

  // Re-register post-processor for detecting inner beans as ApplicationListeners,
  // moving it to the end of the processor chain (for picking up proxies etc).
  // 增加一个自动发现监听器的后处理器
  beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

扩展

问题遗留

参考文献

相关文章

网友评论

      本文标题:4-BeanFactory的增强:ApplicationCont

      本文链接:https://www.haomeiwen.com/subject/icgtchtx.html