概述

[TOC]


本文分析的是 Spring Boot 在基于 Tomcat 的 Servlet 环境下的整体启动及运行流程, 使用到的框架及版本号如下表:

框架 版本号
Spring 5.3.5
Spring Boot 2.5.0-SNAPSHOT
Spring MVC 5.3.5
Spring Boot Starter AOP 2.5.0-SNAPSHOT
Spring Boot Starter Actuator 2.5.0-SNAPSHOT

Spring原理流程图


1、Spring Boot 启动流程分析

1.1、入口类

1.1.1、启动类

@SpringBootApplication
@RestController
@RequestMapping("/")
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

	@GetMapping
	public String getIndex() {
		return "Index";
	}
}

1.1.2、 @SpringBootApplication 注解分析

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
// excludeFilters 表示哪些类不能被扫描到, TypeExcludeFilter.class 和 AutoConfigurationExcludeFilter.class match() 方法返回 true 的在扫描阶段不会被扫描到
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}

SpringBootApplication 注解包含非常重要的三个注解: @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan。

  • @SpringBootConfiguration 包含 @Configuration 注解,表示启动类是个配置类

  • @EnableAutoConfiguration 包含 @AutoConfigurationPackage 和 @Import(AutoConfigurationImportSelector.class) 两个注解

  • @AutoConfigurationPackage 又包含 @Import(AutoConfigurationPackages.Registrar.class) 注解

  • FilterType 取值有以下几个:

    • ANNOTATION // 筛选给定注解标注的候选者
    • ASSIGNABLE_TYPE // 筛选可分配给给定类型的候选者
    • ASPECTJ // 筛选符合指定 AspectJ 类型模式表达式的候选者
    • REGEX // 筛选符合给定正则表达式的候选者
    • CUSTOM // 筛选自定义实现 org.springframework.core.type.filter.TypeFilter 接口的候选者
  • @ComponentScan 在进行 includeFilters 过滤时, 如果useDefaultFilters =true, 它会默认把所有包含 @Component 注解的类都进行扫描因此只有加上 useDefaultFilters=false 才能得到正确的结果。excludeFilters 示例参考。

    /**
     * @description: 测试 @ComponentScan 的 TypeFilter 功能
     */
    public class MyTypeFilter implements TypeFilter {
    	/**
    	 * 扫描匹配
    	 * @param metadataReader 读取到当前正在扫描类的信息
    	 * @param metadataReaderFactory 可以获取到其他任何类信息, 比如父类和接口
    	 */
    	@Override
    	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
    		// 获取当前类注解信息
    		final AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
    		// 获取当前正在扫描的类信息
    		final ClassMetadata classMetadata = metadataReader.getClassMetadata();
    		// 获取当前正在扫描的类的资源信息, 比如类的路径
    		final Resource resource = metadataReader.getResource();
    		String className = classMetadata.getClassName();
    		if(className.contains("Demo")){
    			return true;
    		}
    		return false;
    	}
    }
    
    // 配置完成以后,扫描的时候碰到类名中包含 "Demo" 的字符串的时候就不会扫描了
    @Configuration
    @ComponentScan(excludeFilters = {
    	@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
    })
    public class MyConfig {
    }
    

AutoConfigurationImportSelector 和 AutoConfigurationPackages.Registrar 两个类对于 Spring Boot 的自动化配置, BeanDefinition 扫描过程非常重要,一定要牢记, 参考自动化配置源码分析部分

1.2、SpringApplication 实例化

1.2.1、 实例化源码

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	// 1.2.2、初始化加载资源类集合并去重
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	// 1.2.3、推断应用类型, 三种
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	// 1.2.4、设置 Bootstrapper
	this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
	// 1.2.5、设置初始化器
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	// 1.2.6、设置监听器
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	// 1.2.7、推断主类
	this.mainApplicationClass = deduceMainApplicationClass();
}

1.2.2、初始化加载资源类集合并去重

1.2.3、推断应用类型, 三种

private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" };
private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

static WebApplicationType deduceFromClasspath() {
    // 如果运行环境中包含 WEBFLUX_INDICATOR_CLASS 的字节码, 表示当前运行的是Reactive程序
	if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
		return WebApplicationType.REACTIVE;
	}
	for (String className : SERVLET_INDICATOR_CLASSES) {
		if (!ClassUtils.isPresent(className, null)) {
			return WebApplicationType.NONE;
		}
	}
	return WebApplicationType.SERVLET;
}
  • 如果运行环境中包含 org.springframework.web.reactive.DispatcherHandler 字节码, 表示运行的是 Reactive 程序
  • 如果运行环境中包含 org.springframework.web.servlet.DispatcherServlet 字节码, 表示运行的是 Servlet 程序
  • 如果运行环境中没有包含上面两种, 表示运行的是简单的 Spring 环境

1.2.4、设置 Bootstrapper , 主要用于在使用 BootstrapRegistry 之前初始化它的回调接口

// type 表示 Bootstrapper.class
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
	ClassLoader classLoader = getClassLoader();
    // SpringFactoriesLoader.loadFactoryNames 从 META-INF/spring.factories 加载所有的配置信息,同时放到缓存中
	Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 创建 Bootstrapper 的实例
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
	AnnotationAwareOrderComparator.sort(instances);
	return instances;
}

// 创建扫描到的配置类后实例化并返回给调用端
@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
		ClassLoader classLoader, Object[] args, Set<String> names) {
	List<T> instances = new ArrayList<>(names.size());
	for (String name : names) {
		try {
			Class<?> instanceClass = ClassUtils.forName(name, classLoader);
			Assert.isAssignable(type, instanceClass);
			Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
			T instance = (T) BeanUtils.instantiateClass(constructor, args);
			instances.add(instance);
		} catch (Throwable ex) {
			throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
		}
	}
	return instances;
}
  • 从 META-INF/spring.factories 中加载所有的键值对,并缓存到

    static final Map<ClassLoader, Map<String, List<String>>> cache = new ConcurrentReferenceHashMap<>();
    
  • 获取 META-INF/spring.factories 中配置的 org.springframework.boot.Bootstrapper 的实现类

  • 在 SpringBoot 环境中没有 Bootstrapper 的实现,在 Spring Cloud 环境中有一个实现类 org.springframework.cloud.bootstrap.TextEncryptorConfigBootstrapper

  • Bootstrapper 已废弃 主要作用是在使用 BootstrapRegistry 之前初始化它的回调接口。请使用 BootstrapRegistryInitializer 代替

  • BootstrapRegistry 主要作用是 注册创建代价高昂的实例,或者需要在ApplicationContext可用之前共享的实例,addCloseListener(ApplicationListener)方法可以用来添加一个监听器,当 BootstrapContext 已经关闭且 ApplicationContext 已经完全准备好时,监听器可以执行操作。

1.2.5、设置初始化器 <font color="red">参考初始化器详细分析</font>

  • 参考 1.2.4
  • 初始化器作用
  • 获取 META-INF/spring.factories 中配置的 org.springframework.context.ApplicationContextInitializer 的实现类,实现类有以下七个
    • org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
      • 用来报告Spring容器的一些常见的错误配置
    • org.springframework.boot.context.ContextIdApplicationContextInitializer
      • 在应用程序启动的时候初始化应用程序的唯一ID,如果spring.application.name属性存在,则将其作为ID,否则使用application默认值作为ID
    • org.springframework.boot.context.config.DelegatingApplicationContextInitializer
      • 将初始化的工作委托给context.initializer.classes环境变量指定的初始化器
    • org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer
      • 注入一个端口检查和设置的监听器,对应的事件 RSocketServerInitializedEvent
    • org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
      • 将内置 servlet 容器实际使用的监听端口写入到 Environment 环境变量 local.server.port 中, 然后就可以直接通过 @Value 注入到 Bean 中,或者通过环境属性 Environment 获取
    • org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
      • 创建一个SpringBoot和ConfigurationClassPostProcessor共用的CachingMetadataReaderFactory对象, 同时向容器中注入一个 BeanDefinitionRegistryPostProcessor 的实现类 CachingMetadataReaderFactoryPostProcessor, 在处理 BeanDefinition 过程中使用
    • org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
      • 将 ConditionEvaluationReport 写入到日志, 日志级别为 DEBUG,具体做法是在应用初始化时绑定一个ConditionEvaluationReportListener 事件监听器,然后相应的事件发生时输出ConditionEvaluationReport报告

1.2.6、设置监听器

  • 参考 1.2.4
  • 监听器作用
  • 获取 META-INF/spring.factories 中配置的 org.springframework.context.ApplicationListener 的实现类,实现类有以下七个
    • org.springframework.boot.autoconfigure.BackgroundPreinitializer
      • 对于一些耗时的任务使用一个后台线程尽早触发它们开始执行初始化,这是Springboot的缺省行为。这些初始化动作也可以叫做预初始化。 设置系统属性spring.backgroundpreinitializer.ignore为true可以禁用该机制。 该机制被禁用时,相应的初始化任务会发生在前台线程
    • org.springframework.boot.ClearCachesApplicationListener
      • 清空缓存应用监听器, 该监听器的作用是, 当接收到上下文刷新事件时, 清空当前线程的缓存
    • org.springframework.boot.builder.ParentContextCloserApplicationListener
      • 监听应用上下文刷新事件并从中取出 应用上下文 ,然后监听关闭事件在应用上下文的层级结构中往下层传播该事件。如果父容器关闭,那么子容器也一起关闭。
    • org.springframework.boot.context.FileEncodingApplicationListener
      • 监听 ApplicationEnvironmentPreparedEvent 事件, 通过事件可以获取到 SpringApplication、ConfigurableEnvironment 等等信息, 可以通过 ConfigurableEnvironment 实例对象来修改以及获取默认的环境信息。同时检测当前系统环境的file.encoding和spring.mandatory-file-encoding设置的值是否一样,如果不一样则抛出异常,如果不配置spring.mandatory-file-encoding则不检查
    • org.springframework.boot.context.config.AnsiOutputApplicationListener
      • Ansi输出应用监听器。该监听器的作用是,当收到应用环境准备就绪事件时,对Ansi输出的相关状态进行设置,并绑定到应用环境中。
    • org.springframework.boot.context.config.DelegatingApplicationListener
      • 在应用环境准备就绪事件发生时,通过环境中的配置的 context.listener.classes,去搜集相应的监听器。如果收集到,就会创建一个简单事件广播器实例,放到类属性上,同时,还会把收集到的监听器,绑定到该广播器上。该监听器的另一个特性时,无论发生何事件,只要广播器实例不为空,就利用该广播器广播该事件
    • org.springframework.boot.context.logging.LoggingApplicationListener
      • 从系统中查找LoggingSystem,然后用找到的loggingSystem初始化系统
    • org.springframework.boot.env.EnvironmentPostProcessorApplicationListener
      • SmartApplicationListener 用来触发配置在 spring.factories 文件中的 EnvironmentPostProcessor

1.2.7、推断主类

  • 源码,通过运行中的堆栈信息获取主类

    private Class<?> deduceMainApplicationClass() {
       try {
          StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
          for (StackTraceElement stackTraceElement : stackTrace) {
             if ("main".equals(stackTraceElement.getMethodName())) {
                return Class.forName(stackTraceElement.getClassName());
             }
          }
       } catch (ClassNotFoundException ex) {
       }
       return null;
    }
    

1.3、SpringApplication 的 run 方法

1.3.1、 源码

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	// 1.3.2、创建 Bootstrap 上下文, 多级上下文
	DefaultBootstrapContext bootstrapContext = createBootstrapContext();
	ConfigurableApplicationContext context = null;
    // 配置无头属性
	configureHeadlessProperty();
	// 1.3.3、获取事件发布器
	SpringApplicationRunListeners listeners = getRunListeners(args);
	// 1.3.4、发布 ApplicationStartingEvent, 启动监听器
	// 监听器默认有以下几个, Spring Cloud 环境下还会有其它的一些监听器
	// LoggingApplicationListener
	// BackgroundPreinitializer
	// DelegatingApplicationListener
	// EventPublishingRunListener
	listeners.starting(bootstrapContext, this.mainApplicationClass);
	try {
		// 1.3.5、将传递过来的参数封装到 ApplicationArguments
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		// 1.3.6、准备环境
		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		configureIgnoreBeanInfo(environment);
		// 1.3.7、打印Banner
		Banner printedBanner = printBanner(environment);
		// 1.3.8、创建应用上下文, 同时注册一些 BeanFactoryPostProcessor 和 BeanPostProcessor, 最重要的一个 ConfigurationClassPostProcessor 就是在这里注册的
		context = createApplicationContext();
         // 1.3.16、为容器设置 ApplicationStartup, 标记应用程序启动期间的步骤并收集有关执行上下文或其处理时间的数据
		context.setApplicationStartup(this.applicationStartup);
		// 1.3.9、准备上下文
		prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
		// 1.3.10、刷新上下文
		refreshContext(context);
		// 1.3.11、刷新上下文后调用, 空方法
		afterRefresh(context, applicationArguments);
         // 1.3.12、停止计时器并输出日志记录
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
		// 1.3.13、发布容器启动完成事件
		listeners.started(context);
		// 1.3.14、调用 ApplicationRunner 和 CommandLineRunner
		callRunners(context, applicationArguments);
	} catch (Throwable ex) {
		handleRunFailure(context, ex, listeners);
		throw new IllegalStateException(ex);
	}
	try {
		// 1.3.15、发布容器运行中事件
		listeners.running(context);
	} catch (Throwable ex) {
		handleRunFailure(context, ex, null);
		throw new IllegalStateException(ex);
	}
	return context;
}

1.3.2 、创建 Bootstrap 上下文, 多级上下文

  • 源码, Spring Boot环境下 Bootstrapper 为空,此处只是创建了 DefaultBootstrapContext

    private DefaultBootstrapContext createBootstrapContext() {
       DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
       this.bootstrappers.forEach((initializer) -> initializer.initialize(bootstrapContext));
       return bootstrapContext;
    }
    

1.3.3、获取事件发布器

  • 源码

    private SpringApplicationRunListeners getRunListeners(String[] args) {
       Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
       return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);
    }
    
  • 参考 1.2.4, 获取 META-INF/spring.factories 中配置的 org.springframework.boot.SpringApplicationRunListener 的实现类,实现类目前只有一个

    org.springframework.boot.context.event.EventPublishingRunListener

1.3.4、发布 ApplicationStartingEvent

  • 使用了设计模式中的***观察者模式***, 发布 ApplicationStartingEvent, 监听器有以下几个
    • LoggingApplicationListener
    • BackgroundPreinitializer
    • DelegatingApplicationListener

1.3.5、将传递过来的参数封装到 ApplicationArguments

1.3.6、准备环境

  • 环境部分整体类图如下:

    PropertyResolver

  • 源码,环境部分详细分析请参考 SpringBoot环境分析

    private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    	// 1.3.6.1、创建并配置环境
    	ConfigurableEnvironment environment = getOrCreateEnvironment();
    	// 1.3.6.2、配置环境变量, 1.添加 ConversionService 2.将以 -- 开头启动参数封装成 SimpleCommandLinePropertySource 加入到 Environment 容器中 3.配置profile
    	configureEnvironment(environment, applicationArguments.getSourceArgs());
    	// 1.3.6.3、将 ConfigurationPropertySource 支持附加到指定的环境
        // 将环境管理的每个 PropertySource 调整为 ConfigurationPropertySource
        // 并允许 PropertySourcesPropertyResolver 调用使用配置属性名称进行解析
    	ConfigurationPropertySources.attach(environment);
    	// 1.3.6.4、发布环境准备事件 ApplicationEnvironmentPreparedEvent
    	// 监听器总共有八个
    	// EnvironmentPostProcessorApplicationListener
    	// AnsiOutputApplicationListener
    	// LoggingApplicationListener
    	// BackgroundPreinitializer
    	// DelegatingApplicationListener
    	// ParentContextCloserApplicationListener
    	// ClearCachesApplicationListener
    	// FileEncodingApplicationListener
        // 通过 ConfigDataEnvironmentPostProcessor 环境后置处理器将配置文件封装成 OriginTrackedMapPropertySource  
    	listeners.environmentPrepared(bootstrapContext, environment);
    	// 1.3.6.5、将 defaultProperties 移动到列表末尾
    	DefaultPropertiesPropertySource.moveToEnd(environment);
    	// 1.3.6.6、配置附加的 Profile
    	configureAdditionalProfiles(environment);
    	Assert.state(!environment.containsProperty("spring.main.environment-prefix"), "Environment prefix cannot be set via properties.");
    	// 1.3.6.7、将环境绑定到 spring.main 配置中
        // Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
    	bindToSpringApplication(environment);
    	if (!this.isCustomEnvironment) {
             // 工具类,将一种类型的 Environment 转换成其它类型
    		environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    	}
    	// 1.3.6.3、将 ConfigurationPropertySource 支持附加到指定的环境
        // 将环境管理的每个 PropertySource 调整为 ConfigurationPropertySource
        // 并允许 PropertySourcesPropertyResolver 调用使用配置属性名称进行解析
    	ConfigurationPropertySources.attach(environment);
    	return environment;
    }
    
  • 1.3.6.1、创建并配置环境

    private ConfigurableEnvironment getOrCreateEnvironment() {
        // 判断当前environment是否为null 如果为null 就会创建
    	if (this.environment != null) {
    		return this.environment;
    	}
        // 因为当前是 Servlet 环境,所以此处创建的是 StandardServletEnvironment, 默认创建的是 StandardEnvironment
        // StandardEnvironment 会添加两个环境属性 systemEnvironment, systemProperties
        // StandardServletEnvironment 会添加两个环境属性 servletContextInitParams, servletConfigInitParams,如果是 JNDI 环境会再添加一个jndiProperties
        // StandardReactiveWebEnvironment 不添加环境属性
    	switch (this.webApplicationType) {
    		case SERVLET:
    			return new StandardServletEnvironment();
    		case REACTIVE:
    			return new StandardReactiveWebEnvironment();
    		default:
    			return new StandardEnvironment();
    	}
    }
    
  • 1.3.6.2、配置环境变量

  • 1.3.6.3、将 ConfigurationPropertySource 支持附加到指定的环境

  • 1.3.6.4、发布环境准备事件 ApplicationEnvironmentPreparedEvent, ConfigFileApplicationListener 已废弃,目前使用 ConfigDataEnvironmentPostProcessor 替代。EnvironmentPostProcessor 环境类后置处理器非常重要

    • EnvironmentPostProcessorApplicationListener 监听器负责处理 profile 和加载 properties 和 yaml 配置文件, 配置文件加载流程按照下面的流程图分析即可,流程图详细代码分析请参考 配置文件加载过程

    yaml属性文件加载流程

    • ConfigDataEnvironment 会从以下几个位置加载配置文件

      locations.add(ConfigDataLocation.of("optional:classpath:/"));
      locations.add(ConfigDataLocation.of("optional:classpath:/config/"));
      locations.add(ConfigDataLocation.of("optional:file:./"));
      locations.add(ConfigDataLocation.of("optional:file:./config/"));
      locations.add(ConfigDataLocation.of("optional:file:./config/*/"));
      
    • AnsiOutputApplicationListener 监听器基于 spring.output.ansi.enabled 属性值配置 AnsiOutput

      • PropertySourcesPlaceholdersResolver 解析 spring.output.ansi.enabled
      • PropertyPlaceholderHelper 用于处理包含占位符值的字符串的实用程序类,占位符采用 ${name} 的形式,使用 PropertyPlaceholderHelper 这些占位符可以替换用户提供的值
  • 1.3.6.7、将环境绑定到 spring.main 配置中

1.3.7、打印Banner

  • 源码

    private Banner printBanner(ConfigurableEnvironment environment) {
       if (this.bannerMode == Banner.Mode.OFF) {
          return null;
       }
       ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader : new DefaultResourceLoader(null);
       SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
       if (this.bannerMode == Mode.LOG) {
          return bannerPrinter.print(environment, this.mainApplicationClass, logger);
       }
       return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
    }
    

1.3.8、创建应用上下文, 同时注册一些 BeanFactoryPostProcessor 和 BeanPostProcessor

  • 源码

    protected ConfigurableApplicationContext createApplicationContext() {
       // 如果webApplicationType = SERVLET, 则创建 AnnotationConfigServletWebServerApplicationContext
       // 如果webApplicationType = REACTIVE, 则创建 AnnotationConfigReactiveWebServerApplicationContext
       // 如果webApplicationType = 其它, 则创建 AnnotationConfigApplicationContext
       return this.applicationContextFactory.create(this.webApplicationType);
    }
    
  • 当前是 Servlet 环境,所以创建的是 AnnotationConfigServletWebServerApplicationContext

    public AnnotationConfigServletWebServerApplicationContext() {
       this.reader = new AnnotatedBeanDefinitionReader(this);
       this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
    
  • 创建 AnnotatedBeanDefinitionReader 的时候会同时注册一些 BeanFactoryPostProcessor,非常非常重要 在将注解扫描成 BeanDefinition 和 Bean 的整个处理流程中使用到 

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
       Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
       Assert.notNull(environment, "Environment must not be null");
       this.registry = registry;
       this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
       // 注册一些 BeanFactoryPostProcessor 和 BeanPostProcessor 包括 
       // internalConfigurationAnnotationProcessor - 使用递归方式将注解扫描成 BeanDefinition ,SpringBoot 的自动化配置依赖于这个后置处理器
       // internalAutowiredAnnotationProcessor
       // internalCommonAnnotationProcessor
       // internalPersistenceAnnotationProcessor
       // PersistenceAnnotationBeanPostProcessor
       // internalEventListenerProcessor
       // internalEventListenerFactory
       AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
    
    • org.springframework.context.annotation.internalConfigurationAnnotationProcessor - ConfigurationClassPostProcessor
      • BeanFactoryPostProcessor 的实现类,主要用来处理 @Configuration 配置类
    • org.springframework.context.annotation.internalAutowiredAnnotationProcessor - AutowiredAnnotationBeanPostProcessor
      • BeanPostProcessor 的实现类, 主要用来处理 @Autowired、 @Inject 和 @Value 注解
    • org.springframework.context.annotation.internalCommonAnnotationProcessor - CommonAnnotationBeanPostProcessor
      • BeanPostProcessor 的实现类, 主要用来处理 @PostConstruct、 @PreDestroy 和 @Resource 等注解
    • org.springframework.context.annotation.internalPersistenceAnnotationProcessor - PersistenceAnnotationBeanPostProcessor
    • org.springframework.context.event.internalEventListenerProcessor - EventListenerMethodProcessor
      • BeanFactoryPostProcessor 的实现类, 主要用来将 EventListener 注解的方法注册成 ApplicationListener 的实例
    • org.springframework.context.event.internalEventListenerFactory - DefaultEventListenerFactory
      • 默认的 EventListenerFactory 实现,支持常规的 EventListener 注解

1.3.9、准备上下文

  • 源码

    private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
          ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
          ApplicationArguments applicationArguments, Banner printedBanner) {
       context.setEnvironment(environment);
       postProcessApplicationContext(context);
       // 执行初始化器
       applyInitializers(context);
       // 发布上下文 ApplicationContextInitializedEvent 事件, 共有2个监听器
       // BackgroundPreinitializer
       // DelegatingApplicationListener
       listeners.contextPrepared(context);
       // 发布 BootstrapContextClosedEvent 事件,共有0个监听器
       bootstrapContext.close(context);
       if (this.logStartupInfo) {
          logStartupInfo(context.getParent() == null);
          logStartupProfileInfo(context);
       }
       // 添加特殊的单例 Bean
       ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
       beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
       if (printedBanner != null) {
          beanFactory.registerSingleton("springBootBanner", printedBanner);
       }
       if (beanFactory instanceof DefaultListableBeanFactory) {
          ((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
       }
       if (this.lazyInitialization) {
          context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
       }
       // 加载源
       Set<Object> sources = getAllSources();
       Assert.notEmpty(sources, "Sources must not be empty");
       load(context, sources.toArray(new Object[0]));
       // 发布上下文 ApplicationPreparedEvent 事件,共有 4 个监听器
       listeners.contextLoaded(context);
    }
    
  • ApplicationContextInitializedEvent 事件监听器两个

    • BackgroundPreinitializer
    • DelegatingApplicationListener
  • BootstrapContextClosedEvent 事件监听器 - 无

  • ApplicationPreparedEvent 事件监听器四个

    • EnvironmentPostProcessorApplicationListener
    • LoggingApplicationListener
    • BackgroundPreinitializer
    • DelegatingApplicationListener

1.3.10、刷新上下文

  • 源码

    private void refreshContext(ConfigurableApplicationContext context) {
       if (this.registerShutdownHook) {
          try {
             context.registerShutdownHook();
          } catch (AccessControlException ex) {
          }
       }
       // 调用 ServletWebServerApplicationContext 类的 refresh 方法
       refresh(context);
    }
    @Override
    public final void refresh() throws BeansException, IllegalStateException {
    	try {
             // 调用 AbstractApplicationContext 的 refresh 方法 
    		super.refresh();
    	} catch (RuntimeException ex) {
    		WebServer webServer = this.webServer;
    		if (webServer != null) {
    			webServer.stop();
    		}
    		throw ex;
    	}
    }
    
  • 调用 AbstractApplicationContext 类的 refresh 方法, 参考 2.1.1

1.3.11、刷新上下文后调用, 空方法

  • 模板方法模式, 交给子类去实现, Spring Boot 环境中没有实现, 是一个空方法

1.3.12、停止计时器并输出日志记录

1.3.13、发布容器启动完成事件 ApplicationStartedEvent ,共两个监听器

  • BackgroundPreinitializer

  • DelegatingApplicationListener

1.3.14、调用 ApplicationRunner 和 CommandLineRunner

  • 源码

    private void callRunners(ApplicationContext context, ApplicationArguments args) {
       List<Object> runners = new ArrayList<>();
       runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
       runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
       AnnotationAwareOrderComparator.sort(runners);
       for (Object runner : new LinkedHashSet<>(runners)) {
          if (runner instanceof ApplicationRunner) {
             callRunner((ApplicationRunner) runner, args);
          }
          if (runner instanceof CommandLineRunner) {
             callRunner((CommandLineRunner) runner, args);
          }
       }
    }
    
  • 示例:

    @Configuration
    public class ProducerApplication implements ApplicationRunner {
    	private final ServiceProperties serviceProperties;
    	public ProducerApplication(ServiceProperties serviceProperties) {
    		this.serviceProperties = serviceProperties;
    	}
    	@Override
    	public void run(ApplicationArguments args) throws Exception {
    		this.serviceProperties.getInputDir().mkdirs();
    		if (!args.getNonOptionArgs().isEmpty()) {
    			FileOutputStream stream = new FileOutputStream(new File(this.serviceProperties.getInputDir(), "data" + System.currentTimeMillis() + ".txt"));
    			for (String arg : args.getNonOptionArgs()) {
    				stream.write(arg.getBytes());
    			}
    			stream.flush();
    			stream.close();
    		}
    	}
    	public static void main(String[] args) {
    		SpringApplication.run(ProducerApplication.class, args);
    	}
    }
    

1.3.15、发布容器运行中事件 ApplicationReadyEvent 共三个监听器, 扩展点

  • BackgroundPreinitializer
  • DelegatingApplicationListener
  • SpringApplicationAdminMXBeanRegistrar

1.3.16、为容器设置 ApplicationStartup, 标记应用程序启动期间的步骤并收集有关执行上下文或其处理时间的数据

  • ApplicationStartup 使用方法示例

    public static void main(String[] args) throws InterruptedException {
    	SpringApplication app = new SpringApplication(Application.class);
    	BufferingApplicationStartup applicationStartup = new BufferingApplicationStartup(1024);
    	// 父模块启动记录
    	StartupStep step = applicationStartup.start("startup-first-step");
    	// 子模块启动记录
    	StartupStep stepChild =  applicationStartup.start("startup-first-step-child").tag("demo", "application");
    	Thread.sleep(1000);
    	// 子模块结束记录
    	stepChild.end();
    	Thread.sleep(1000);
    	// 父模块结束记录
    	step.end();
    	app.setApplicationStartup(applicationStartup);
    	app.run(args);
    }
    
  • 项目内引入 spring-boot-starter-actuator 模块,配置文件中配置暴露的接口 management.endpoints.web.exposure.include=startup 启动应用后访问 http://localhost:8090/actuator/startup 可以看到 spring 启动的每个阶段耗时。性能分析时使用


2、Spring 启动流程分析

2.1、1.3.10 刷新上下文 会执行到此处

2.1.1、源码

@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
		// 2.1.2、准备刷新容器
		prepareRefresh();
		// 2.1.3、告诉子类刷新内部的 BeanFactory
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		// 2.1.4、准备上下文中使用的 BeanFactory
		prepareBeanFactory(beanFactory);
		try {
             // 2.1.5、允许在上下文子类中对 Bean 工厂进行后置处理
			postProcessBeanFactory(beanFactory);
			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
             // 2.1.6、调用注册到上下文中的 Bean 工厂后置处理器
			invokeBeanFactoryPostProcessors(beanFactory);
             // 2.1.7、注册 Bean 后置处理器在 Bean 的创建过程中进行拦截
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();
			// 2.1.8、初始化国际化功能
			initMessageSource();
             // 2.1.9、初始化事件广播器
			initApplicationEventMulticaster();
             // 2.1.10、初始化指定子类上下文中的特殊 Bean, 非常重要
			onRefresh();
             // 2.1.11、检查监听器 Bean 并且注册他们
			registerListeners();
             // 2.1.12、实例化所有 non-lazy-init 的单例 Bean
			finishBeanFactoryInitialization(beanFactory);
			// 2.1.13、发布刷新完成事件
			finishRefresh();
		} catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + ex);
			}
             // 销毁所有已经创建的单例避免内存泄漏
			destroyBeans();
             // 重置 active 标识
			cancelRefresh(ex);
			// 抛出异常
			throw ex;
		} finally {
			resetCommonCaches();
			contextRefresh.end();
		}
	}
}
  • ApplicationStartup 和 StartupStep 源码分析及示例 TODO

2.1.2、准备刷新容器

  • 源码

    protected void prepareRefresh() {
       // 修改标识状态, 切换为激活状态
       this.startupDate = System.currentTimeMillis();
       this.closed.set(false);
       this.active.set(true);
       if (logger.isDebugEnabled()) {
          if (logger.isTraceEnabled()) {
             logger.trace("Refreshing " + this);
          } else {
             logger.debug("Refreshing " + getDisplayName());
          }
       }
       // 初始化上下文环境中的任何占位符属性
       initPropertySources();
       // 校验所有被标记为 required 的属性是否已经解析到
       // 查看 ConfigurablePropertyResolver#setRequiredProperties
       getEnvironment().validateRequiredProperties();
       if (this.earlyApplicationListeners == null) {
          this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
       } else {
          this.applicationListeners.clear();
          this.applicationListeners.addAll(this.earlyApplicationListeners);
       }
       // 当广播器可用的时候允许广播 early ApplicationEvent 集合
       this.earlyApplicationEvents = new LinkedHashSet<>();
    }
    

2.1.3、告诉子类刷新内部的 BeanFactory

  • 在 Spring 环境中会注册一些内部 Bean , 但是 Spring Boot 环境下其实就是设置一些状态
  • 调用 GenericApplicationContext 然后再调用 DefaultListableBeanFactory
  • 在非 SpringBoot 环境中相当于 1.3.8

2.1.4、准备上下文中使用的 BeanFactory

  • 注册一些 BeanPostProcessor , 并添加一些要忽略的依赖接口,源码

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
       // 告诉内部 Bean 工厂使用上下文的类加载器
       beanFactory.setBeanClassLoader(getClassLoader());
       if (!shouldIgnoreSpel) {
          beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
       }
       beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
       // 使用上下文回调方法配置 BeanFactory 
       beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
       // 忽略以下几个接口的实现类中,对外的依赖
       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.ignoreDependencyInterface(ApplicationStartupAware.class);
       // MessageSource 注册(并用于自动发现装配)为 bean
       // 指定该类型接口,如果外部要注入该类型接口的对象,则会注入我们指定的对象,而不会去管其他接口实现类
       beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
       beanFactory.registerResolvableDependency(ResourceLoader.class, this);
       beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
       beanFactory.registerResolvableDependency(ApplicationContext.class, this);
       // 将用于检测内部 bean 的早期后置处理器注册为 ApplicationListeners
       beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
       // 检测 LoadTimeWeaver 并且准备织入,如果找到的话
       if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
          beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
          // 为类型匹配设置一个临时的 ClassLoader
          beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
       }
       // 注册默认的环境 Bean
       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());
       }
       if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
          beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
       }
    }
    
  • ignoreDependencyInterface 方法,被忽略的接口会存储在 BeanFactory 的名为 ignoredDependencyInterfaces 的 Set 集合中

  • ignoreDependencyType 方法, 被忽略的接口存储在 BeanFactory 的名为 ignoredDependencyTypes 的 Set 集合中

  • ignoreDependencyInterface 和 ignoreDependencyType 配合 BeanPostProcessor 可实现自定义 aware 接口,示例如下:

    public interface IgnoreInterface {
    	void setList(List<String> list);
    	void setUser(User user);
    }
    public class IgnoreInterfaceAImpl implements IgnoreInterface {
    	private List<String> list;
    	private User user;
    	private Set<String> set;
    	@Override
    	public void setList(List<String> list) {
    		this.list = list;
    	}
    	@Override
    	public void setUser(User user) {
    		this.user = user;
    	}
    	public void setSet(Set<String> set) {
    		this.set = set;
    	}
    }
    public class IgnoreInterfaceBImpl implements IgnoreInterface {
    	private List<String> list;
    	private User user;
    	private Set<String> set;
    	@Override
    	public void setList(List<String> list) {
    		this.list = list;
    	}
    	@Override
    	public void setUser(User user) {
    		this.user = user;
    	}
    	public void setSet(Set<String> set) {
    		this.set = set;
    	}
    }
    @Configuration
    public class IgnoreInterfaceConfig {
    	@Bean
    	public IgnoreInterfaceAImpl ignoreInterfaceAImpl() {
    		IgnoreInterfaceAImpl ignoreInterfaceA = new IgnoreInterfaceAImpl();
    		Set<String> strings = new HashSet<>();
    		strings.add("测试");
    		ignoreInterfaceA.setSet(strings);
    		return ignoreInterfaceA;
    	}
    	@Bean
    	public IgnoreInterfaceBImpl ignoreInterfaceBImpl() {
    		IgnoreInterfaceBImpl ignoreInterfaceB = new IgnoreInterfaceBImpl();
    		Set<String> strings = new HashSet<>();
    		strings.add("测试");
    		ignoreInterfaceB.setSet(strings);
    		return ignoreInterfaceB;
    	}
    	@Bean
    	public List<String> list() {
    		List<String> list = new ArrayList<>();
    		list.add("测试list");
    		return list;
    	}
    	@Bean
    	public User user() {
    		User user = new User();
    		user.setName("测试name");
    		return user;
    	}
    }
    // 默认 IgnoreInterfaceAImpl 和 IgnoreInterfaceBImpl 的三个属性都可以正常注入
    @Component
    public class IgnoreAutowiringProcessor implements BeanFactoryPostProcessor {
    	@Override
    	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    		// beanFactory.ignoreDependencyType(List.class);
    		// beanFactory.ignoreDependencyType(Student.class);
             // 忽略 list 和 user 的注入
    		beanFactory.ignoreDependencyInterface(IgnoreInterface.class);
    	}
    }
    
  • registerResolvableDependency 指定该类型接口,如果外部要注入该类型接口的对象,则会注入我们指定的对象,而不会去管其他接口实现类。示例如下:

    public interface MyComponent {
    }
    @Component
    public class MyComponentAImpl implements MyComponent {
    	private String mark = "a";
    }
    @Component
    public class MyComponentBImpl implements MyComponent {
    	private String mark = "b";
    }
    // 直接注入会报错, 容器不知道具体应该注入哪个类
    @Component
    public class TestInject {
    	@Autowired
    	protected MyComponent myComponent;
    }
    // 加上下面的 BeanFactoryPostProcessor 后就不会报错了, 容器注入的时候指定注入 MyComponentAImpl
    // 当然也可以使用 @Primary 解决注入冲突问题
    @Component
    public class ResolvableDependencyPostProcess implements BeanFactoryPostProcessor {
    	@Override
    	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    		beanFactory.registerResolvableDependency(MyComponent.class, new MyComponentAImpl());
    	}
    }
    

2.1.5、允许在上下文子类中对 Bean 工厂进行后置处理

  • 调用 AnnotationConfigServletWebServerApplicationContext 的 postProcessBeanFactory 方法

  • 调用 ServletWebServerApplicationContext 的 postProcessBeanFactory 方法添加 WebApplicationContextServletContextAwareProcessor 的 BeanPostProcessor 用于向 Bean 注入 ConfigurableWebApplicationContext 应用上下文

  • 源码

    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
       // 调用父类 ServletWebServerApplicationContext 的 postProcessBeanFactory 方法
       super.postProcessBeanFactory(beanFactory);
       if (this.basePackages != null && this.basePackages.length > 0) {
          this.scanner.scan(this.basePackages);
       }
       if (!this.annotatedClasses.isEmpty()) {
          this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
       }
    }
    

2.1.6、调用注册到上下文中的 Bean 工厂后置处理器

  • 通过 BeanFactoryPostProcessor 用扫描到的类生成 BeanDefinition 并注入到容器中的流程。BeanFactoryPostProcessor 作用于 BeanDefinition 的整个过程中, 而 BeanPostProcessor 作用于 Bean 的整个过程中,两个后置处理器不要混淆

    配置文件加载及BeanDefinition加载流程分析

    // 类 - AbstractApplicationContext
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
       PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
       // 检测 LoadTimeWeaver 并且准备织入 weaving
       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
    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        // 首先调用 BeanDefinitionRegistryPostProcessors 的 postProcessBeanDefinitionRegistry 
    	Set<String> processedBeans = new HashSet<>();
    	if (beanFactory instanceof BeanDefinitionRegistry) {
    		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    				BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;
    				registryProcessor.postProcessBeanDefinitionRegistry(registry);
    				registryProcessors.add(registryProcessor);
    			} else {
    				regularPostProcessors.add(postProcessor);
    			}
    		}
    		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
             // 首先调用实现了 PriorityOrdered 的 BeanDefinitionRegistryPostProcessors 
    		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);
             // 非常重要, SpringBoot 的自动化配置就在此处实现,递归调用 ConfigurationClassPostProcessor 的 postProcessBeanDefinitionRegistry 方法
    		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    		currentRegistryProcessors.clear();
    		// 调用实现了 Ordered 接口的 BeanDefinitionRegistryPostProcessors
    		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();
             // 调用所有其它的 BeanDefinitionRegistryPostProcessors 直到没有更多的出现
    		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();
    		}
             // 调用到目前为止处理的所有后置处理器的 postProcessBeanFactory 回调
    		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    	} else {
    		// 调用在上下文实例中注册的工厂处理器.
    		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    	}
    	// 不要在此处初始化 FactoryBean, 保留所有未初始化的常规 Bean,让 BeanFactoryPostProcessor 处理它们
    	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
        // 将实现了 PriorityOrdered、 Ordered 和其它接口的 BeanFactoryPostProcessors 分开
    	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    	List<String> orderedPostProcessorNames = new ArrayList<>();
    	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    	for (String ppName : postProcessorNames) {
    		if (processedBeans.contains(ppName)) {
    			// 跳过,已经处理过
    		} 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);
    		}
    	}
        // 调用实现了 PriorityOrdered 接口的 BeanFactoryPostProcessors
    	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // 调用实现了 Ordered 接口的 BeanFactoryPostProcessors
    	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    	for (String postProcessorName : orderedPostProcessorNames) {
    		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    	}
    	sortPostProcessors(orderedPostProcessors, beanFactory);
    	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
        // 调用所有剩余的 BeanFactoryPostProcessors 
    	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    	for (String postProcessorName : nonOrderedPostProcessorNames) {
    		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    	}
    	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
        // 清除缓存的合并 bean 定义,因为后置处理器可能已经修改了原始元数据,例如 替换值中的占位符
    	beanFactory.clearMetadataCache();
    }
    
  • 以 ConfigurationClassPostProcessor BeanFactory 后置处理器解释后置处理器的所有执行流程

  • @EnableAutoConfiguration, @Import, @ConfigurationProperties 等注解都是在此处处理

  • 详细分析请参考 BeanDefinition生成及注入流程

2.1.7、注册 Bean 后置处理器在 Bean 的创建过程中进行拦截

  • 注册 Bean 的后置处理器, 源码

    protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
       PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
    }
    
    // 类 - PostProcessorRegistrationDelegate
    public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
        // 注册 BeanPostProcessorChecker, 当 Bean 在 BeanPostProcessor 实例化的时候被创建输出一条 INFO 级别的日志
        // 当一个 bean 没有资格被所有 BeanPostProcessor 处理时
    	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        // 注册 BeanPostProcessorChecker 
    	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    	// 将实现了 PriorityOrdered、Ordered 和其它接口的 BeanPostProcessors 分开
    	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) {
    				internalPostProcessors.add(pp);
    			}
    		} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    			orderedPostProcessorNames.add(ppName);
    		} else {
    			nonOrderedPostProcessorNames.add(ppName);
    		}
    	}
        // 注册实现了 PriorityOrdered 接口的 BeanPostProcessors
    	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // 此处注册 ConfigurationPropertiesBindingPostProcessor CommonAnnotationBeanPostProcessor AutowiredAnnotationBeanPostProcessor
    	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
        // 注册实现了 Ordered 接口的 BeanPostProcessors
        // 如果 pom.xml 文件中添加了 spring-boot-starter-aop 模块,则此处会注册一个 aop 处理的 BeanPostProcessor
        // org.springframework.aop.config.internalAutoProxyCreator = AnnotationAwareAspectJAutoProxyCreator
    	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    	for (String ppName : orderedPostProcessorNames) {
    		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    		orderedPostProcessors.add(pp);
    		if (pp instanceof MergedBeanDefinitionPostProcessor) {
    			internalPostProcessors.add(pp);
    		}
    	}
    	sortPostProcessors(orderedPostProcessors, beanFactory);
        // 此处注册 AnnotationAwareAspectJAutoProxyCreator
    	registerBeanPostProcessors(beanFactory, orderedPostProcessors);
        // 注册所有常规的 BeanPostProcessors
    	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    	for (String ppName : nonOrderedPostProcessorNames) {
    		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
    		nonOrderedPostProcessors.add(pp);
    		if (pp instanceof MergedBeanDefinitionPostProcessor) {
    			internalPostProcessors.add(pp);
    		}
    	}
        // 此处注册 WebServerFactoryCustomizerBeanPostProcessor ErrorPageRegistrarBeanPostProcessor HealthEndpointConfiguration.HealthEndpointGroupsBeanPostProcessor
    	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
        // 重新注册所有内部的 BeanPostProcessors
    	sortPostProcessors(internalPostProcessors, beanFactory);
        // 此处注册 CommonAnnotationBeanPostProcessor AutowiredAnnotationBeanPostProcessor
    	registerBeanPostProcessors(beanFactory, internalPostProcessors);
    	// 重新注册后处理器以将内部 bean 检测为 ApplicationListeners,将其移动到处理器链的末尾(用于获取代理等)
    	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }
    
  • 共注册了 11 个 BeanPostProcessor, 在 Bean 实例化和初始化的过程中使用

  • ApplicationContextAwareProcessor

  • WebApplicationContextServletContextAwareProcessor

  • ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor

  • PostProcessorRegistrationDelegate.BeanPostProcessorChecker

  • ConfigurationPropertiesBindingPostProcessor

  • WebServerFactoryCustomizerBeanPostProcessor

  • ErrorPageRegistrarBeanPostProcessor

  • CommonAnnotationBeanPostProcessor

  • AutowiredAnnotationBeanPostProcessor

  • ApplicationListenerDetector

2.1.8、初始化国际化功能

  • 源码

    protected void initMessageSource() {
       ConfigurableListableBeanFactory beanFactory = getBeanFactory();
       if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
          this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
          // 使 MessageSource 感知到父 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());
             }
          }
          if (logger.isTraceEnabled()) {
             logger.trace("Using MessageSource [" + this.messageSource + "]");
          }
       } else {
          // 使用空的 MessageSource 接受 getMessage 调用
          DelegatingMessageSource dms = new DelegatingMessageSource();
          dms.setParentMessageSource(getInternalParentMessageSource());
          this.messageSource = dms;
          beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
          if (logger.isTraceEnabled()) {
             logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
          }
       }
    }
    

2.1.9、初始化事件广播器

  • 源码

    public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "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);
          if (logger.isTraceEnabled()) {
             logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
          }
       } else {
          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() + "]");
          }
       }
    }
    

2.1.10、初始化指定子类上下文中的特殊 Bean

  • 典型的模板方法模式,父类定义好模板和调用流程, 委托给子类实现。在 Servlet 环境中用来创建并启动 Tomcat 容器, 参考 Tomcat启动流程分析

    protected void onRefresh() {
    	super.onRefresh();
    	try {
    		createWebServer();
    	} catch (Throwable ex) {
    		throw new ApplicationContextException("Unable to start web server", ex);
    	}
    }
    
    private void createWebServer() {
    	WebServer webServer = this.webServer;
    	ServletContext servletContext = getServletContext();
    	if (webServer == null && servletContext == null) {
    		StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
    		ServletWebServerFactory factory = getWebServerFactory();
    		createWebServer.tag("factory", factory.getClass().toString());
    		this.webServer = factory.getWebServer(getSelfInitializer());
    		createWebServer.end();
    		getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer));
    		getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer));
    	} else if (servletContext != null) {
    		try {
    			getSelfInitializer().onStartup(servletContext);
    		} catch (ServletException ex) {
    			throw new ApplicationContextException("Cannot initialize servlet context", ex);
    		}
    	}
    	initPropertySources();
    }
    
  • createWebServer() 为 Tomcat 启动部分, 参考 Tomcat启动流程分析

2.1.11、检查监听器 Bean 并且注册他们

  • 源码

    protected void registerListeners() {
       // 注册静态的指定的监听器
       for (ApplicationListener<?> listener : getApplicationListeners()) {
          getApplicationEventMulticaster().addApplicationListener(listener);
       }
       String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
       for (String listenerBeanName : listenerBeanNames) {
          // &org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
          // mvcResourceUrlProvider
          // springApplicationAdminRegistrar
          // applicationAvailability
          getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
       }
       // 有了一个多播器,发布早期的应用程序事件
       Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
       this.earlyApplicationEvents = null;
       if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
          for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
             getApplicationEventMulticaster().multicastEvent(earlyEvent);
          }
       }
    }
    
  • 添加 12 个事件监听器,监听器如下

    • ConditionEvaluationReportLoggingListener.ConditionEvaluationReportListener
    • RSocketPortInfoApplicationContextInitializer.Listener
    • ServerPortInfoApplicationContextInitializer
    • EnvironmentPostProcessorApplicationListener
    • AnsiOutputApplicationListener
    • LoggingApplicationListener
    • BackgroundPreinitializer
    • DelegatingApplicationListener
    • ParentContextCloserApplicationListener
    • ClearCachesApplicationListener
    • FileEncodingApplicationListener
    • SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean

2.1.12、实例化所有 non-lazy-init 的单例 Bean

  • Bean 生成流程图

  • 几个非常重要的 BeanPostProcessor 及子接口

    // 第一个: BeanPostProcessor
    
    // 初始化之前的操作    
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;    
    // 初始化之后的操作    
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
    
    
    // 第二个: InstantiationAwareBeanPostProcessor
    
    // postProcessBeforeInstantiation 方法的作用在目标对象被实例化之前调用的方法,可以返回目标实例的一个代理用来代替目标实例
    // beanClass参数表示目标对象的类型, beanName是目标实例在Spring容器中的name
    // 返回值类型是Object,如果返回的是非null对象,接下来除了postProcessAfterInitialization方法会被执行以外,其它bean构造的那些方法都不再执行。否则那些过程以及postProcessAfterInitialization方法都会执行
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
    // postProcessAfterInstantiation方法的作用在目标对象被实例化之后并且在属性值被populate之前调用
    // bean参数是目标实例(这个时候目标对象已经被实例化但是该实例的属性还没有被设置),beanName是目标实例在Spring容器中的name
    // 返回值是boolean类型,如果返回true,目标实例内部的返回值会被populate,否则populate这个过程会被忽视
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
    // postProcessPropertyValues方法的作用在属性中被设置到目标实例之前调用,可以修改属性的设置
    // pvs参数表示参数属性值(从BeanDefinition中获取),pds代表参数的描述信息(比如参数名,类型等描述信息),bean参数是目标实例,beanName是目标实例在Spring容器中的name
    // 返回值是PropertyValues,可以使用一个全新的PropertyValues代替原先的PropertyValues用来覆盖属性设置或者直接在参数pvs上修改。如果返回值是null,那么会忽略属性设置这个过程(所有属性不论使用什么注解,最后都是null)
    PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
    
    
    // 第三个: RequiredAnnotationBeanPostProcessor
    
    // 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
    Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;
    // 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
    // beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name
    // 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
    Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;
    // 获得提前暴露的bean引用。主要用于解决循环引用的问题
    // 只有单例对象才会调用此方法
    Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
    
    
    // 第四个: DestructionAwareBeanPostProcessor 
    
    // 该方法是bean在Spring在容器中被销毁之前调用
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
    
  • 初始化和实例化所有 non-lazy-init 的单例 Bean

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
       // 为容器初始化类型转换服务 CONVERSION_SERVICE_BEAN_NAME
       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));
       }
       // 如果之前没有注册过类似 PropertySourcesPlaceholderConfigurer 的 Bean, 这里注册一个默认的值解析器,主要用于解析 @Value 注解
       if (!beanFactory.hasEmbeddedValueResolver()) {
          beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
       }
       // 提前初始化 LoadTimeWeaverAware Beans 用来提前注册他们的转换器
       String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
       for (String weaverAwareName : weaverAwareNames) {
          getBean(weaverAwareName);
       }
       // 停止使用临时的 ClassLoader 进行类型匹配
       beanFactory.setTempClassLoader(null);
       // 允许缓存所有的 BeanDefinition 的元数据, 不会再有进一步的变化了
       beanFactory.freezeConfiguration();
       // 实例化所有剩余的 (non-lazy-init) 单例 Bean
       beanFactory.preInstantiateSingletons();
    }
    
  • beanFactory.preInstantiateSingletons() 是整个 Bean 实例化和初始化流程中开始的地方

  • @Value 注解解析的整个流程如下:

    Value注解解析流程

2.1.13、发布刷新完成事件

  • 容器刷新完成,同时发布 ContextRefreshedEvent 事件,事件监听器有 15 个

    @SuppressWarnings("deprecation")
    protected void finishRefresh() {
    	// 清除上下文级资源缓存(例如来自扫描的 ASM 元数据)
    	clearResourceCaches();
    	// 为此上下文初始化生命周期处理器
    	initLifecycleProcessor();
    	// 首先将刷新事件传播到生命周期处理器
    	getLifecycleProcessor().onRefresh();
    	// 广播最终的事件
    	publishEvent(new ContextRefreshedEvent(this));
    	if (!NativeDetector.inNativeImage()) {
    		LiveBeansView.registerApplicationContext(this);
    	}
    }
    
  • 扩展点 可以监听 ContextRefreshedEvent 事件在应用完全启动完成后执行一些操作


感谢您的反馈。如果您有关于如何使用 KubeSphere 的具体问题,请在 Slack 上提问。如果您想报告问题或提出改进建议,请在 GitHub 存储库中打开问题。

页面内容