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();
}

目录
相关文章
|
1月前
|
Java Spring
使用JDBCTemplate实现与Spring结合,方法公用 ——测试(EmpDaoImplTest)
使用JDBCTemplate实现与Spring结合,方法公用 ——测试(EmpDaoImplTest)
9 0
|
3天前
|
XML Java 数据格式
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
手写spring第七章-完成便捷实现bean对象初始化和销毁方法
6 0
|
3天前
|
设计模式 存储 Java
手写spring第二章-运用设计模式编写可扩展的容器
手写spring第二章-运用设计模式编写可扩展的容器
7 0
|
5天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
10天前
|
安全 Java API
第1章 Spring Security 概述(2024 最新版)(下)
第1章 Spring Security 概述(2024 最新版)
21 0
|
10天前
|
安全 Java 数据安全/隐私保护
第1章 Spring Security 概述(2024 最新版)(上)
第1章 Spring Security 概述(2024 最新版)
27 0
|
12天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
28天前
|
负载均衡 网络协议 Java
构建高效可扩展的微服务架构:利用Spring Cloud实现服务发现与负载均衡
本文将探讨如何利用Spring Cloud技术实现微服务架构中的服务发现与负载均衡,通过注册中心来管理服务的注册与发现,并通过负载均衡策略实现请求的分发,从而构建高效可扩展的微服务系统。
|
1月前
|
Java Spring
使用JDBCTemplate实现与Spring结合,方法公用 ——Emp实现类(EmpDaoImpl)
使用JDBCTemplate实现与Spring结合,方法公用 ——Emp实现类(EmpDaoImpl)
8 0
|
1月前
|
Java Spring
使用JDBCTemplate实现与Spring结合,方法公用 ——共用实现类(BaseImpl)
使用JDBCTemplate实现与Spring结合,方法公用 ——共用实现类(BaseImpl)
10 1