Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)(上)

简介: Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)

前言

Spring 核心方法 refresh 刷新流程简要概述及相关源码剖析(一)

继上章分析的继续补充 Refresh 中未分析完的其他方法

registerBeanPostProcessors

在 Spring 中, AbstractApplicationContext#registerBeanPostProcessors 方法被调用时,会把所有匹配的 BPP 实现类进行实例化并且加载到容器中,以便后面进行 Bean 初始化时进行一一调用

public static void registerBeanPostProcessors(
       ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
   // 找到所有实现了 BeanPostProcessor 接口的类
   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.
   // 记录下 BeanPostProcessor 目标数
   // 此处 +1 是因为此方法的后面会添加一个 BeanPostProcessorChecker 类
   int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
   // 添加 BeanPostProcessorChecker(主要用于记录信息)到 beanFactory 中
   beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
   // 定义存放实现了 PriorityOrdered 接口 BeanPostProcessor 集合
   List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
   // 定义存放 spring 内部的 BeanPostProcessor
   List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
   // 定义存放实现了 Ordered 接口的 BeanPostProcessor  name 集合
   List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
   // 定义存放普通的 BeanPostProcessor  name 集合
   List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
   // 遍历beanFactory中存在的BeanPostProcessor的集合postProcessorNames,
   for (String ppName : postProcessorNames) {
       BeanPostProcessor bpp = null;
       // 如果ppName对应的BeanPostProcessor实例实现了PriorityOrdered接口,则获取到ppName对应的BeanPostProcessor的实例添加到priorityOrderedPostProcessors中
       if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
           bpp = beanFactory.getBean(ppName, BeanPostProcessor.class);
           priorityOrderedPostProcessors.add(bpp);
       }
       // 如果ppName对应的BeanPostProcessor实例没有实现PriorityOrdered接口,但是实现了Ordered接口,那么将ppName对应的bean实例添加到orderedPostProcessorNames中
       else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
           // orderedPostProcessorNames.add(ppName);
           bpp = beanFactory.getBean(ppName, BeanPostProcessor.class);
           orderedPostProcessors.add(bpp);
       } else {
           // 否则将ppName添加到nonOrderedPostProcessorNames中
           // nonOrderedPostProcessorNames.add(ppName);
           bpp = beanFactory.getBean(ppName, BeanPostProcessor.class);
           nonOrderedPostProcessors.add(bpp);
       }
       // 如果ppName对应的BeanPostProcessor实例也实现了MergedBeanDefinitionPostProcessor接口,那么则将ppName对应的bean实例添加到internalPostProcessors中
       if (bpp instanceof MergedBeanDefinitionPostProcessor) {
           internalPostProcessors.add(bpp);
       }
   }
   // First, register the BeanPostProcessors that implement PriorityOrdered.
   // 首先,对实现了PriorityOrdered接口的BeanPostProcessor实例进行排序操作
   sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
   // 注册实现了PriorityOrdered接口的BeanPostProcessor实例添加到beanFactory中
   registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
   // Next, register the BeanPostProcessors that implement Ordered.
   // 注册所有实现Ordered的beanPostProcessor
   // List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
   /*for (String ppName : orderedPostProcessorNames) {
       // 根据ppName找到对应的BeanPostProcessor实例对象
       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
       // 将实现了Ordered接口的BeanPostProcessor添加到orderedPostProcessors集合中
       orderedPostProcessors.add(pp);
       // 如果ppName对应的BeanPostProcessor实例也实现了MergedBeanDefinitionPostProcessor接口,那么则将ppName对应的bean实例添加到internalPostProcessors中
       if (pp instanceof MergedBeanDefinitionPostProcessor) {
           internalPostProcessors.add(pp);
       }
   }*/
   // 对实现了Ordered接口的BeanPostProcessor进行排序操作
   sortPostProcessors(orderedPostProcessors, beanFactory);
   //  注册实现了Ordered接口的BeanPostProcessor实例添加到beanFactory中
   registerBeanPostProcessors(beanFactory, orderedPostProcessors);
   // Now, register all regular BeanPostProcessors.
   // 创建存放没有实现PriorityOrdered和Ordered接口的BeanPostProcessor的集合
   // List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
   // 遍历集合
   /*for (String ppName : nonOrderedPostProcessorNames) {
       // 根据ppName找到对应的BeanPostProcessor实例对象
       BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
       // 将没有实现PriorityOrdered和Ordered接口的BeanPostProcessor添加到nonOrderedPostProcessors集合中
       nonOrderedPostProcessors.add(pp);
       // 如果ppName对应的BeanPostProcessor实例也实现了MergedBeanDefinitionPostProcessor接口,那么则将ppName对应的bean实例添加到internalPostProcessors中
       if (pp instanceof MergedBeanDefinitionPostProcessor) {
           internalPostProcessors.add(pp);
       }
   }*/
   //  注册没有实现PriorityOrdered和Ordered的BeanPostProcessor实例添加到beanFactory中
   registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
   // Finally, re-register all internal BeanPostProcessors.
   // 将所有实现了MergedBeanDefinitionPostProcessor类型的BeanPostProcessor进行排序操作
   sortPostProcessors(internalPostProcessors, beanFactory);
   // 注册所有实现了MergedBeanDefinitionPostProcessor类型的BeanPostProcessor到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).
   // 注册ApplicationListenerDetector到beanFactory中
   beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

对以上方法流程使用图结构和文案进行详细阅览

  1. beanFactory#getBeanNamesForType(BeanPostProcessor.class:通过 BPP 类型从 beanDefinitionNames 中找到其实现类,返回 String[] 类名数
  2. 记录 BPP 目标数量,此处 +1 原因是因为在此方法调用的后面添加了一个 BeanPostProcessorChecker 类「该类用于检测完 Bean 以后记录的日志信息」
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
  1. 创建存储实现 PriorityOrdered 接口、Ordered 接口、两者都未实现的接口【noOrdered】集合,再创建一个实现了 MergedBeanDefinitionPostProcessor 接口类型的内部集合,最后对 BPP 类数组进行遍历,判断其类型是属于哪一种,再加入到对应的集合中.
  2. 对以上四种集合进行同样的操作,按照顺序进行:PriorityOrdered —>Ordered —> noOrdered —> MergedBeanDefinitionPostProcessor

对集合中元素进行排序

向容器中注册给定的 BPP 类型的 Bean

  1. 注册 ApplicationListenerDetector 到容器中,该 BPP 在 prepareBeanFactory 中已经注册过了,再次注册只是为了后续可以直接取用

initMessageSource

上下文初始化 message 源,即不同的语言消息体,进行国际化处理,向容器中注入该 bean 实例

protected void initMessageSource() {
    // 获取bean工厂,一般是 DefaultListableBeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 首先判断是否已有xml文件定义了id为messageSource的bean对象
    if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
        // 如果有,则从BeanFactory中获取这个对象
        this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
        // 当父类bean工厂不为空,并且这个bean对象是HierarchicalMessageSource类型
        if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
            // 类型强制转换,转换为HierarchicalMessageSource的类型
            HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
            // 判断父类的messageSource是否为空,如果等于空,则设置父类的messageSource
            if (hms.getParentMessageSource() == null) {
                hms.setParentMessageSource(getInternalParentMessageSource());
            }
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Using MessageSource [" + this.messageSource + "]");
        }
    }
    else {
        // 如果没有xml文件定义信息源对象,新建DelegatingMessageSource类作为messageSource的bean
        DelegatingMessageSource dms = new DelegatingMessageSource();
        // 给这个DelegatingMessageSource添加父类消息源
        dms.setParentMessageSource(getInternalParentMessageSource());
        this.messageSource = dms;
        // 将这个messageSource实例注册到bean工厂中
        beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
        }
    }
}

如果程序中没有进行重定义这个 MessageSource 消息源 Bean,Spring 会默认帮我们注入一个 DelegatingMessageSource 实例

如何实际应用国际化处理

在公司中使用的国际化处理 Bean 一般是 ReloadableResourceBundleMessageSource,它可以帮我们解析 xml、properties 文件,同时可以自定义编码格式

public class LocaleConfig {
    @Resource
    private PlatformConfig platformConfig;
    /**
     * 加载一下语言资源
     **/
    @Bean("messageSource")
    @ConditionalOnMissingBean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        // 用分号隔开各个语言资源路径
        String[] paths = platformConfig.getPath().split(PlatformConstants.COLON);
        messageSource.setBasenames(paths);
        messageSource.setDefaultEncoding(platformConfig.getEncoding());
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setFallbackToSystemLocale(false);
        return messageSource;
    }
    /**
     * 默认解析器 其中locale表示默认语言
     */
    @Bean
    public LocaleResolver localeResolver() {
        return new I18nLocaleResolver();
    }
    /**
     * 获取请求头国际化信息
     */
    static class I18nLocaleResolver implements LocaleResolver {
        @NotNull
        @Override
        public Locale resolveLocale(HttpServletRequest httpServletRequest) {
            String languageHeader = httpServletRequest.getHeader(PlatformConstants.LANGUAGE);
            String languageParameter = httpServletRequest.getParameter(PlatformConstants.LANGUAGE);
            String language = Objects.nonNull(languageHeader) ? languageHeader : languageParameter;
            Locale locale = Locale.getDefault();
            if (!StringUtils.isEmpty(language)) {
                String[] split = language.split(PlatformConstants.UNDERSCORE);
                locale = new Locale(split[0], split[1]);
            }
            return locale;
        }
        @Override
        public void setLocale(@NotNull HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
        }
    }
}

配置消息源核心 Bean 以后,再配置下面的上下文国际化语言 MsgKey 内容处理,前端在 header 中传入当前的国家语言编码,后端在拦截器或者全局异常处理器调用 LocalContext#get 方法返回翻译值

public class LocalContent {
    private static MessageSource messageSource;
    public LocalContent(@Qualifier("messageSource") MessageSource messageSource) {
        LocalContent.messageSource = messageSource;
    }
    /**
     * 获取单个国际化翻译值
     */
    public static String get(String msgKey) {
        return messageSource.getMessage(msgKey, null, LocaleContextHolder.getLocale());
    }
}

initApplicationEventMulticaster

初始化事件监听多路广播器

protected void initApplicationEventMulticaster() {
    // 获取当前bean工厂,一般是DefaultListableBeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 判断容器中是否存在 beanName 为 applicationEventMulticaster 的 bd,也就是说自定义的事件监听多路广播器,必须实现 ApplicationEventMulticaster 接口
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        // 如果有,则从 bean 工厂得到这个 bean 对象
        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 多路广播器类,它的父类 AbstractApplicationEventMulticaster 的内部类专门用一个集合来存储所有的监听器

// 创建监听器助手类,用于存放应用程序的监听器集合,参数是否是预过滤监听器为 false
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
private class ListenerRetriever {
    // ApplicationListener 对象集合
    public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
    // BeanFactory 中的 applicationListener 类型 Bean 集合
    // 在设置监听器时会通过 beanName 去获取监听器,再放入 applicationListeners 集合中
    public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
.......
}

onRefresh

该方法留给子类去实现,没有添加任何实现,以 SpringBoot 为例

ServletWebServerApplicationContext

protected void onRefresh() {
    // 创建主题对象
  super.onRefresh();
  /*
  GenericWebApplicationContext
  protected void onRefresh() {
    this.themeSource = UiApplicationContextUtils.initThemeSource(this);
  }
  */
  try {
      // 开始创建 web 服务->tomcat
    createWebServer();
  } catch (Throwable ex) {
    throw new ApplicationContextException("Unable to start web server", ex);
  }
}

registerListeners

在所有注册的 Bean 中查找监听器,同时将监听器注册到消息广播器中,在这里就涉及到事件的发布以及事件的处理,详细内容可以阅读该文章:Spring 消息源及监听机制

protected void registerListeners() {
    // 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }
    // 从容器中获取所有实现了ApplicationListener接口的bd的bdName
    // 放入 ApplicationListenerBeans 集合中
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        // 可以直接获取监听器实例进去,无须在取用的时候再次 getBean getApplicationEventMulticaster().addApplicationListener(this.getBean(listenerBeanName,ApplicationListener.class));
    }
    // 此处先发布早期的监听器集合
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

finishBeanFactoryInitialization

实例化&初始化 Bean(非懒加载的),如果是实现了 FactoryBean 接口的话,就是懒加载的,只有当某个实例调用它的 getObject 方法才会去加载实现了 FactoryBean 接口的类实例.

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));
  }
  // Register a default embedded value resolver if no bean post-processor
  // (such as a PropertyPlaceholderConfigurer bean) registered any before:
  // at this point, primarily for resolution in annotation attribute values.
  // 如果beanFactory之前没有注册嵌入值解析器,则注册默认的嵌入值解析器,主要用于注解属性值的解析
  if (!beanFactory.hasEmbeddedValueResolver()) {
    beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
  }
  // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
  // 尽早初始化 loadTimeWeaverAware bean,以便尽早注册它们的转换器
  String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
  for (String weaverAwareName : weaverAwareNames) {
    getBean(weaverAwareName);
  }
  // Stop using the temporary ClassLoader for type matching.
  // 禁止使用临时类加载器进行类型匹配
  beanFactory.setTempClassLoader(null);
  // Allow for caching all bean definition metadata, not expecting further changes.
  // 冻结所有的bean定义,说明注册的bean定义将不被修改或任何进一步的处理
  beanFactory.freezeConfiguration();
  // 实例化剩下的单例对象
  beanFactory.preInstantiateSingletons();
}

目录
相关文章
|
3天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
19天前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
19天前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
17天前
|
Java 数据库连接 数据库
让星星⭐月亮告诉你,SSH框架01、Spring概述
Spring是一个轻量级的Java开发框架,旨在简化企业级应用开发。它通过IoC(控制反转)和DI(依赖注入)降低组件间的耦合度,支持AOP(面向切面编程),简化事务管理和数据库操作,并能与多种第三方框架无缝集成,提供灵活的Web层支持,是开发高性能应用的理想选择。
22 1
|
19天前
|
XML Java 数据格式
手动开发-简单的Spring基于注解配置的程序--源码解析
手动开发-简单的Spring基于注解配置的程序--源码解析
35 0
|
19天前
|
XML Java 数据格式
手动开发-简单的Spring基于XML配置的程序--源码解析
手动开发-简单的Spring基于XML配置的程序--源码解析
61 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
19天前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
100 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
19天前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
37 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块