【小家Spring】Spring IOC容器启动流程 AbstractApplicationContext#refresh()方法源码分析(二),Spring容器启动/刷新的完整总结(上)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 【小家Spring】Spring IOC容器启动流程 AbstractApplicationContext#refresh()方法源码分析(二),Spring容器启动/刷新的完整总结(上)

前言


在上一篇文章:【小家Spring】Spring IOC容器启动流程 AbstractApplicationContext#refresh()方法源码分析(一)中已经介绍了前五步,现在Spring IOC容器的工厂环境已经都准备好了。


Bean工厂可以简单理解为一个钩子容器,里面注册有众多的BeanFactoryPostProcessor以及BeanFactoryPostProcessor,接下来我们就前去学习钩子的细节~


Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

Spring源码基于的Spring版本为:5.0.6.RELEASE(下同)

refresh() 第六步:registerBeanPostProcessors(beanFactory)


在讲解这个方法之前先看下什么是BeanPostProcessor,下面是BeanPostProcessor的代码:

public interface BeanPostProcessor {
  // 在Bean实例化/依赖注入完毕以及自定义的初始化方法之前调用。什么叫自定义初始化方法:比如init-method、比如@PostConstruct标、比如实现InitailztingBean接口的方法等等
  // bean:这个Bean实例  beanName:bean名称
  @Nullable
  default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }
  // 在上面基础上,初始化方法之后调用
  @Nullable
  default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }
}


口中两个方法不能返回null,如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象 ,因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中


BeanFactory和ApplicationContext注册Bean的后置处理器不通点:


ApplicationContext直接使用@Bean注解,就能向容器注册一个后置处理器。

原因:它注册Bean的时候,会先检测是否实现了BeanPostProcessor接口,并自动把它们注册为后置处理器。所在在它这部署一个后置处理器和注册一个普通的Bean,是没有区别的


BeanFactory必须显示的调用:void addBeanPostProcessor(BeanPostProcessor beanPostProcessor才能注册进去。


Spring 可以注册多个Bean的后置处理器,是按照注册的顺序进行调用的。若想定制顺序,可以实现@Order或者实现Order接口~


源码解读


先说说:((DefaultListableBeanFactory) beanFactory).getBeanPostProcessors();这个方法:


  public List<BeanPostProcessor> getBeanPostProcessors() {
    return this.beanPostProcessors;
  }


它返回的是所有的通过BeanFactory#addBeanPostProcessor方法添加进去的后置处理器们,会存在这个List里面。


image.png


image.png


还有就是这个内部类:(一共4个,是容器启动时,用BeanFactory添加进去的Bean后置处理器)


image.png


而这个方法getBeanNamesForType是从Bean定义信息里面去找:主要是如下几个属性缓存上的:

(所以请注意和getBeanPostProcessors的结果区分开来,虽然都是BeanPostProcessor)


  /** Map of bean definition objects, keyed by bean name */
  private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
  /** Map of singleton and non-singleton bean names, keyed by dependency type */
  private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
  /** Map of singleton-only bean names, keyed by dependency type */
  private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
  /** List of bean definition names, in registration order */
  private volatile List<String> beanDefinitionNames = new ArrayList<>(256);


这些其实就是IOC容器的本质:一堆Map


具体源码:

  // 发现它又是委托给PostProcessorRegistrationDelegate 去做的
  protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
  }
  public static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    // 从所与Bean定义中提取出BeanPostProcessor类型的Bean,显然,最初的6个bean,有三个是BeanPostProcessor:
    // AutowiredAnnotationBeanPostProcessor  RequiredAnnotationBeanPostProcessor  CommonAnnotationBeanPostProcessor
    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.
    // 此处有点意思了,向beanFactory又add了一个BeanPostProcessorChecker,并且此事后总数设置为了getBeanPostProcessorCount和addBeanPostProcessor的总和(+1表示自己)
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 此处注意:第一个参数beanPostProcessorTargetCount表示的是处理器的总数,总数(包含两个位置离的,用于后面的校验)
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 同样的 先按优先级,归类了BeanPostProcessor
    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);
        // MergedBeanDefinitionPostProcessor则是在合并处理Bean定义的时候的回调。这个东东按我的理解也基本是框架内部使用的,用户不用管
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
          internalPostProcessors.add(pp);
        }
      }
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
        orderedPostProcessorNames.add(ppName);
      }
      else {
        nonOrderedPostProcessorNames.add(ppName);
      }
    }
    // First, register the BeanPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    // Next, register the BeanPostProcessors that implement Ordered.
    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);
    // 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) {
        internalPostProcessors.add(pp);
      }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    // Finally, re-register all internal BeanPostProcessors.
    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).
    // 最后此处需要注意的是:Spring还给我们注册了一个Bean的后置处理器:ApplicationListenerDetector  它的作用:用来检查所有得ApplicationListener
    // 有的人就想问了:之前不是注册过了吗,怎么这里又注册一次呢?其实上面的doc里面说得很清楚:
    // Re-register重新注册这个后置处理器。把它移动到处理器连条的最后面,最后执行(小技巧是:先remove,然后执行add操作~~~ 自己可以点进addBeanPostProcessor源码可以看到这个小技巧)
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
  }
  // 把类型是BeanPostProcessor的Bean,注册到beanFactory里面去
  private static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    for (BeanPostProcessor postProcessor : postProcessors) {
      beanFactory.addBeanPostProcessor(postProcessor);
    }
  }


这一步:我们从所有的@Bean定义中抽取出来了BeanPostProcessor然后都注册进去,等待后面的的顺序调用


refresh() 第七步:initMessageSource()


初始化消息源。


  protected void initMessageSource() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 判断是否已经存在名为“messageSource”的Bean了(一般情况下,我们都是没有的)
    if (beanFactory.containsLocalBean(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());
        }
      }
    }
    else {
      // Use empty MessageSource to be able to accept getMessage calls.
      DelegatingMessageSource dms = new DelegatingMessageSource();
      // 其实就是获取到父容器的messageSource字段(否则就是getParent()上下文自己)
      dms.setParentMessageSource(getInternalParentMessageSource());
      // 给当前的messageSource赋值
      this.messageSource = dms;
      // 把messageSource作为一个单例的Bean注册进beanFactory工厂里面
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
    }
  }


这部分逻辑比较简单:向容器里注册一个一个事件源的单例Bean:MessageSource


refresh() 第八步:initApplicationEventMulticaster()


初始化Spring的事件多播器:ApplicationEventMulticaster


  protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    } else {
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); 
    }
  }


这个逻辑太简单了,一句话:若用户自己定义了这个Bean(备注:Bean名称必须是"applicationEventMulticaster"哦),就以用户的为准。否则注册一个系统默认的SimpleApplicationEventMulticaster


refresh() 第九步:onRefresh()


类似于第四步的postProcessBeanFactory,它也是个模版方法。本环境中的实现为:AbstractRefreshableWebApplicationContext#onRefresh方法:

  @Override
  protected void onRefresh() {
    this.themeSource = UiApplicationContextUtils.initThemeSource(this);
  }


web环境,所以去初始化了它的主题。



 context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"));
 context.start();




相关文章
|
17天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
38 2
|
1月前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
3月前
|
XML Java 测试技术
spring复习01,IOC的思想和第一个spring程序helloWorld
Spring框架中IOC(控制反转)的思想和实现,通过一个简单的例子展示了如何通过IOC容器管理对象依赖,从而提高代码的灵活性和可维护性。
spring复习01,IOC的思想和第一个spring程序helloWorld
|
1月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
39 0
|
2月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
144 9
|
2月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
38 0
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
3月前
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
46 4
|
2月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
79 0
|
3月前
|
XML Java 开发者
经典面试---spring IOC容器的核心实现原理
作为一名拥有十年研发经验的工程师,对Spring框架尤其是其IOC(Inversion of Control,控制反转)容器的核心实现原理有着深入的理解。
151 3
|
2月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
53 0
下一篇
DataWorks