Spring系列一之springboot启动(上)

2024-08-01 17:57:07 浏览数 (1)

1 整体流程

Springboot的启动核心run方法如下

代码语言:javascript复制
public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();
    // 1.创建BootstrapContext
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    // 2.headless模式配置
    configureHeadlessProperty();
    // 3.获取SpringApplicationRunListeners,执行starting方法
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
       // 4.解析应用的启动参数
       ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       // 5.准备运行时环境
       ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
       // 6.是否忽略BeanInfo类的搜索
       configureIgnoreBeanInfo(environment);
       // 7.打印Banner
       Banner printedBanner = printBanner(environment);
       // 8.创建ApplicationContext
       context = createApplicationContext();
       context.setApplicationStartup(this.applicationStartup);
       // 9.初始化IOC容器
       prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
       // 10.刷新IOC容器
       refreshContext(context);
       // 11.刷新后处理
       afterRefresh(context, applicationArguments);
       Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
       if (this.logStartupInfo) {
          new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
       }
       listeners.started(context, timeTakenToStartup);
       // 12.回调Runner
       callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
       handleRunFailure(context, ex, listeners);
       throw new IllegalStateException(ex);
    }
    try {
       Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
       listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
       handleRunFailure(context, ex, null);
       throw new IllegalStateException(ex);
    }
    return context;
}

从以上代码中可以看出,整个启动流程还是比较清晰的,下面依次来看看每个步骤的具体逻辑

2 DefaultBootstrapContext

先简单介绍下DefaultBootstrapContext,它是BootstrapContext的一个默认实现,作用是可以用于为创建复杂的单例,或者是需要在容器初始化之前使用的单例,并且提供了延迟访问的机制,延迟访问主要是通过InstanceSupplier实现,下文中有讲到。

使用的时机如下图所示

启动开始时,在listeners.starting(bootstrapContext,this.mainApplicationClass)处使用

在准备ConfigurableEnvironment时使用

最后在prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner)方法中,在listeners执行完contextPrepared方法后调用了DefaultBootstrapContext的close方法,close方法发布了一个BootstrapContextClosedEvent事件,可见在此之后DefaultBootstrapContext的生命周期就结束了

BootstrapContextBootstrapContext
PrepareContextPrepareContext

DefaultBootstrapContext中的核心方法和属性如下

PropertyAndMethodPropertyAndMethod

持有两个Map,instances和instanceSuppliers,其中instances是存储对象实例,instanceSuppliers存储对象实例的提供者(可以理解为实例的工厂),它们的key是class对象,因此是用于单例的存储

events是个事件广播器,上面讲到的关闭事件就是用它发布的

close监听及事件相关的方法,用于发布关闭事件,回调监听者

get方法,获取的是instances中存储的实例,结合代码可以看到instances中的实例又是由instanceSuppliers生产提供

register方法,注册的是instanceSupplier,用于生产instance实例

下面来看看流程中第一步createBootstrapContext()

代码语言:javascript复制
private DefaultBootstrapContext createBootstrapContext() {
    DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
    this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
    return bootstrapContext;
}

其实就是使用了bootstrapRegistryInitializers,依次调用initializer.initialize方法初始化,而bootstrapRegistryInitializers的获取是在SpringApplication的构造器中通过getSpringFactoriesInstances方法获取,如下

代码语言:javascript复制
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.bootstrapRegistryInitializers = new ArrayList<>(
          getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

在getSpringFactoriesInstances方法中其实最终就是利用Springboot的SPI机制从spring.factories文件中加载bootstrapRegistryInitializers,并且在以上代码中还获取ApplicationListener和ApplicationContextInitializer,后文中分析其作用

3 Headless配置

Headless模式是系统的一种配置模式,在该模式下,系统缺少了显示设备、键盘或鼠标。 Headless模式虽然不是我们愿意见到的,但事实上我们却常常需要在该模式下工作,尤其是服务器端程序开发者。因为服务器(如提供Web服务的主机)往往可能缺少前述设备,但又需要使用他们提供的功能,生成相应的数据,以提供给客户端(如浏览器所在的配有相关的显示设备、键盘和鼠标的主机),此时就可以使用Headless模式来提供简单的显示设备、键盘或鼠标的功能,代码比较简单,如下

代码语言:javascript复制
private void configureHeadlessProperty() {
    System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
          System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

如果配置了SYSTEM_PROPERTY_JAVA_AWT_HEADLESS就使用配置的值,否则使用默认值(true)

4 SpringApplicationRunListeners

SpringApplicationRunListener是在整个启动流程中不同执行点事件通知的监听者,接口定义如下

代码语言:javascript复制
public interface SpringApplicationRunListener {
    // run方法被调用后立即执行
    default void starting(ConfigurableBootstrapContext bootstrapContext) {}
    // 当environment构建完成,ApplicationContext创建之前执行
    default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
          ConfigurableEnvironment environment) {}
    // 当ApplicationContext创建完成,但是资源还没有加载之前执行
    default void contextPrepared(ConfigurableApplicationContext context) {}
    // 当ApplicationContext资源加载完成,但是刷新之前执行
    default void contextLoaded(ConfigurableApplicationContext context) {}
    // 当ApplicationContext刷新并启动之后,但是CommandLineRunner和ApplicationRunner执行之前执行
    default void started(ConfigurableApplicationContext context, Duration timeTaken) {
       started(context);
    }
    // 同上,但是已经被弃用since 2.6.0
    @Deprecated
    default void started(ConfigurableApplicationContext context) {}
    // 在run方法完成之前执行
    default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
       running(context);
    }
    // 同上,但是已经被弃用since 2.6.0
    @Deprecated
    default void running(ConfigurableApplicationContext context) {}
    // 在run方法抛异常的时候执行
    default void failed(ConfigurableApplicationContext context, Throwable exception) {}
}

获取SpringApplicationRunListener的方法也比较简单,就是利用Springboot的SPI机制从spring.factories文件中加载,如下

代码语言:javascript复制
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);
}

在启动的过程当中,只加载了一个SpringApplicationRunListener,就是EventPublishingRunListener

EventPublishingRunListenerEventPublishingRunListener

获取到EventPublishingRunListeners之后,调用了listeners.starting(bootstrapContext,this.mainApplicationClass)方法

代码语言:javascript复制
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
    doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
          (step) -> {
             if (mainApplicationClass != null) {
                step.tag("mainApplicationClass", mainApplicationClass.getName());
             }
          });
}

在starting方法中依次调用各个listener的starting方法,所有来看看EventPublishingRunListener的starting方法,如下

代码语言:javascript复制
public void starting(ConfigurableBootstrapContext bootstrapContext) {
    this.initialMulticaster
       .multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}

可以看到就是利用initialMulticaster发布了一个ApplicationStartingEvent事件。

到这里简单总结下,在启动调用run方法之后立即调用SpringApplicationRunListeners的starting方法,而SpringApplicationRunListeners是一个代理,内部维护了一个SpringApplicationRunListener列表,启动时只加载了一个EventPublishingRunListener,然后通过EventPublishingRunListener发布一个ApplicationStartingEvent事件,那又是谁来监听ApplicationStartingEvent呢,继续看multicastEvent方法

代码语言:javascript复制
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    Executor executor = getTaskExecutor();
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
       if (executor != null) {
          executor.execute(() -> invokeListener(listener, event));
       }
       else {
          invokeListener(listener, event);
       }
    }
}

从上面代码可以看出multicastEvent方法中又调用getApplicationListeners方法根据事件类型获取了对应的ApplicationListener,而getApplicationListeners又调用了retrieveApplicationListeners方法,如下

代码语言:javascript复制
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
       ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {
    ......
    Set<ApplicationListener<?>> listeners;
    Set<String> listenerBeans;
    synchronized (this.defaultRetriever) {
       listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
       listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
    }
    ......
}

在retrieveApplicationListeners方法中我们看到这里主要从this.defaultRetriever中获取ApplicationListener,而defaultRetriever的ApplicationListener又是从哪里来的呢?这里的this对象是initialMulticaster,所以我们再回过头看看在initialMulticaster的创建过程,如下

代码语言:javascript复制
public EventPublishingRunListener(SpringApplication application, String[] args) {
    this.application = application;
    this.args = args;
    this.initialMulticaster = new SimpleApplicationEventMulticaster();
    for (ApplicationListener<?> listener : application.getListeners()) {
       this.initialMulticaster.addApplicationListener(listener);
    }
}

initialMulticaster是在EventPublishingRunListener的构造方法中创建,并且从SpringApplication中获取ApplicationListener并且通过initialMulticaster.addApplicationListener方法添加,如下

代码语言:javascript复制
public void addApplicationListener(ApplicationListener<?> listener) {
    synchronized (this.defaultRetriever) {
       // Explicitly remove target for a proxy, if registered already,
       // in order to avoid double invocations of the same listener.
       Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
       if (singletonTarget instanceof ApplicationListener) {
          this.defaultRetriever.applicationListeners.remove(singletonTarget);
       }
       this.defaultRetriever.applicationListeners.add(listener);
       this.retrieverCache.clear();
    }
}

在addApplicationListener方法中将ApplicationListener添加到defaultRetriever,而SpringApplication中的ApplicationListener是在新建SpringApplication对象是从spring.factories文件中加载,上面已经提到过。

5 PrepareEnvironment

第四步解析启动参数比较简单就略过,下面来看看运行时环境准备,代码如下

代码语言:javascript复制
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
       DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // 根据webApplicationType创建environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 配置environment
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // attachsources
    ConfigurationPropertySources.attach(environment);
    // 发布environmentPrepared事件
    listeners.environmentPrepared(bootstrapContext, environment);
    // 将默认的source移到最后
    DefaultPropertiesPropertySource.moveToEnd(environment);
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
          "Environment prefix cannot be set via properties.");
    // 绑定spring.main开头的属性配置到SpringApplication对应的field
    bindToSpringApplication(environment);
    // 判断environment是否需要转换
    if (!this.isCustomEnvironment) {
       EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
       environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    // 重新再attachsources一次
    ConfigurationPropertySources.attach(environment);
    return environment;
}

下面依次看看各个步骤

getOrCreateEnvironment(),代码如下

代码语言:javascript复制
// 本质上是遍历所有的ApplicationContextFactory实例(也是
// 从spring.factories文件中加载),看和webApplicationType是否匹配,匹配就创建对应的environment 
// spring有两种ApplicationContextFactory,如下
// AnnotationConfigReactiveWebServerApplicationContext$Factory,webfluxserver
// AnnotationConfigServletWebServerApplicationContext$Factory,servletserver
// 这里最终创建的是ApplicationServletEnvironment
private ConfigurableEnvironment getOrCreateEnvironment() {
    if (this.environment != null) {
       return this.environment;
    }
    ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType);
    if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
       environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType);
    }
    return (environment != null) ? environment : new ApplicationEnvironment();
}

configureEnvironment(environment, applicationArguments.getSourceArgs()),代码如下

代码语言:javascript复制
// 为environment设置ApplicationConversionService,主要是做类型转换和格式化的
// 另外还将命令行参数也设置到environment中,configureProfiles为空实现
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    if (this.addConversionService) {
       environment.setConversionService(new ApplicationConversionService());
    }
    configurePropertySources(environment, args);
    configureProfiles(environment, args);
}

ConfigurationPropertySources.attach(environment),代码如下

代码语言:javascript复制
// 将名称为configurationProperties的PropertySource添加到第一个,优先级最高
public static void attach(Environment environment) {
    Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
    MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
    PropertySource<?> attached = getAttached(sources);
    if (attached == null || !isUsingSources(attached, sources)) {
       attached = new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
             new SpringConfigurationPropertySources(sources));
    }
    sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
    sources.addFirst(attached);
}

listeners.environmentPrepared(bootstrapContext, environment)和listeners.starting类似发布了一个ApplicationEnvironmentPreparedEvent事件,然后获取到对应事件的EnvironmentPostProcessor处理器列表依次处理,我们的默认application.properties和application-{profile}.properties就是在这些处理器中加载的(处理器的逻辑就不一一列举了),如下所示

application.propertiesapplication.properties

DefaultPropertiesPropertySource.moveToEnd(environment),将名称为defaultProperties的移动到最后,优先级最低

代码语言:javascript复制
public static void moveToEnd(MutablePropertySources propertySources) {
    PropertySource<?> propertySource = propertySources.remove(NAME);
    if (propertySource != null) {
       propertySources.addLast(propertySource);
    }
}

bindToSpringApplication(environment),如果配置文件中配置了以spring.main开头的属性配置,在这里会绑定到SpringAppliction类对应的field上

代码语言:javascript复制
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
    try {
       Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
    }
    catch (Exception ex) {
       throw new IllegalStateException("Cannot bind to SpringApplication", ex);
    }
}

environment = environmentConverter.convertEnvironmentIfNecessary(environment,deduceEnvironmentClass()),这里是判断environment是否需要转换,其实这里创建的environment就是根据Type去创建出来的,所以一般类型是吻合的,不需要转换,最后再次执行attachResource,将configurationProperties属性源优先级提到最高,这样environment就准备完成了

6 是否忽略BeanInfo类的搜索

设置是否忽略BeanInfo类的搜索,spring在根据Class获取BeanInfo时是通过Java的Introspector工具获取,获取的时候可以设置是否忽略BeanInfo类的搜索,默认是不忽略,如下所示

代码语言:javascript复制
BeanInfo beanInfo = (shouldIntrospectorIgnoreBeaninfoClasses ?
       Introspector.getBeanInfo(beanClass, Introspector.IGNORE_ALL_BEANINFO) :
       Introspector.getBeanInfo(beanClass));
代码语言:javascript复制
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
    if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
       Boolean ignore = environment.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
             Boolean.class, Boolean.TRUE);
       System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
    }
}

7 创建ApplicationContext

打印Banner部分就不看了,直接看创建ApplicationContext

代码语言:javascript复制
protected ConfigurableApplicationContext createApplicationContext() {
    return this.applicationContextFactory.create(this.webApplicationType);
}

和environment一样通过applicationContextFactory创建,applicationContextFactory.create——>getFromSpringFactories

代码语言:javascript复制
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
       BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
    for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
          getClass().getClassLoader())) {
       T result = action.apply(candidate, webApplicationType);
       if (result != null) {
          return result;
       }
    }
    return (defaultResult != null) ? defaultResult.get() : null;
}

上文中提到applicationContextFactory只有两种实现,AnnotationConfigReactiveWebServerApplicationContext$Factory和 AnnotationConfigServletWebServerApplicationContext$Factory,所以这里是通过后者的create方法创建,继续跟进

代码语言:javascript复制
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
    return (webApplicationType != WebApplicationType.SERVLET) ? null
          : new AnnotationConfigServletWebServerApplicationContext();
}

AnnotationConfigServletWebServerApplicationContext$Factory的create方法就只是New了一个AnnotationConfigServletWebServerApplicationContext出来直接返回,看下构造方法做了什么

代码语言:javascript复制
public AnnotationConfigServletWebServerApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

如上,构造方法定义了reader的scanner,这两个类都是用来加载BeanDefinition,scanner主要是用来扫描指定的包下带注解的类,而reader主要是用来动态显示注册一些spring扫描不到的类,比如spring完成扫描是需要解析Appconfig.java当中的@ComponentScan注解的值(一般是一个包名),得到这个值之后用scanner去扫描这个值所代表的包下面的所有bean,由于这里使用的是AnnotationConfigServletWebServerApplicationContext的无参构造器,所以会先依次调用父类的无参构造器

这里看下父类GenericApplicationContext的无参构造器

代码语言:javascript复制
public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

可以看到在这里新建了beanFactory,使用的是DefaultListableBeanFactory

再来看看新建AnnotatedBeanDefinitionReader时做了什么

代码语言:javascript复制
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);
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

新建AnnotatedBeanDefinitionReader时最终是调用以上的构造器创建,最后一行注册了一些基础的处理器,比如处理@Autowired自动注入的processor,如下

BasicBeanDefinitionBasicBeanDefinition

8 初始化IOC容器

ApplicationContext创建好了之后开始初始化IOC容器,初始化代码如下

代码语言:javascript复制
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
       ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
       ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    applyInitializers(context);
    listeners.contextPrepared(context);
    bootstrapContext.close(context);
    if (this.logStartupInfo) {
       logStartupInfo(context.getParent() == null);
       logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if (printedBanner != null) {
       beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
       ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
       if (beanFactory instanceof DefaultListableBeanFactory) {
          ((DefaultListableBeanFactory) beanFactory)
             .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
       }
    }
    if (this.lazyInitialization) {
       context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    listeners.contextLoaded(context);
}

下面依次看看各个步骤

context.setEnvironment(environment),为context、reader、scanner设置运行时环境

代码语言:javascript复制
public void setEnvironment(ConfigurableEnvironment environment) {
    super.setEnvironment(environment);
    this.reader.setEnvironment(environment);
    this.scanner.setEnvironment(environment);
}

postProcessApplicationContext(context),如果我们在初始化SpringApplication时为之设置了beanNameGenerator或resourceLoader,则会在此方法中注册到BeanFactory或设置到ApplicationContext。除此之外,ConversionService是初始化Environment时候就有的,也会在这里被设置到BeanFactory

代码语言:javascript复制
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
    if (this.beanNameGenerator != null) {
       context.getBeanFactory()
          .registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator);
    }
    if (this.resourceLoader != null) {
       if (context instanceof GenericApplicationContext) {
          ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader);
       }
       if (context instanceof DefaultResourceLoader) {
          ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader());
       }
    }
    if (this.addConversionService) {
       context.getBeanFactory().setConversionService(context.getEnvironment().getConversionService());
    }
}

applyInitializers(context),首先initializers列表,在新建SpringApplication时就已经通过SPI加载了,然后依次调用ApplicationContextInitializer的initialize方法

代码语言:javascript复制
protected void applyInitializers(ConfigurableApplicationContext context) {
    for (ApplicationContextInitializer initializer : getInitializers()) {
       Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
             ApplicationContextInitializer.class);
       Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
       initializer.initialize(context);
    }
}

bootstrapContext.close(context),bootstrapContext的生命周期到此就结束了,发布了一个close事件

logStartupInfo主要就是在打印banner之后打印一些启动信息,如下

StartupInfoStartupInfo

之后就是注册ApplicationArgrument和Banner,设置BeanFactory是否循序循环引用,是否允许覆盖注册,默认都是false

context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()),如果需要延迟初始化,默认false,则需要注册一个LazyInitializationBeanFactoryPostProcessor,在BeanDefinition加载完成之后将BeanDefinition的lazyInit属性设置成true,如下

代码语言:javascript复制
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    Collection<LazyInitializationExcludeFilter> filters = getFilters(beanFactory);
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
       BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
       if (beanDefinition instanceof AbstractBeanDefinition) {
          postProcess(beanFactory, filters, beanName, (AbstractBeanDefinition) beanDefinition);
       }
    }
}
private void postProcess(ConfigurableListableBeanFactory beanFactory,
       Collection<LazyInitializationExcludeFilter> filters, String beanName,
       AbstractBeanDefinition beanDefinition) {
    Boolean lazyInit = beanDefinition.getLazyInit();
    if (lazyInit != null) {
       return;
    }
    Class<?> beanType = getBeanType(beanFactory, beanName);
    if (!isExcluded(filters, beanName, beanDefinition, beanType)) {
       beanDefinition.setLazyInit(true);
    }
}

context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context)),注册一个PropertySourceOrderingBeanFactoryPostProcessor,主要作用是再次将defaultProperties属性源的优先级调到最低,如下

代码语言:javascript复制
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    DefaultPropertiesPropertySource.moveToEnd(this.context.getEnvironment());
}

Set<Object> sources = getAllSources(),获取primarySources和sources,primarySources就是引用的启动类,sources默认是空

代码语言:javascript复制
public Set<Object> getAllSources() {
    Set<Object> allSources = new LinkedHashSet<>();
    if (!CollectionUtils.isEmpty(this.primarySources)) {
       allSources.addAll(this.primarySources);
    }
    if (!CollectionUtils.isEmpty(this.sources)) {
       allSources.addAll(this.sources);
    }
    return Collections.unmodifiableSet(allSources);
}

load(context, sources.toArray(newObject[0]))

代码语言:javascript复制
protected void load(ApplicationContext context, Object[] sources) {
    if (logger.isDebugEnabled()) {
       logger.debug("Loading source "   StringUtils.arrayToCommaDelimitedString(sources));
    }
    BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
    if (this.beanNameGenerator != null) {
       loader.setBeanNameGenerator(this.beanNameGenerator);
    }
    if (this.resourceLoader != null) {
       loader.setResourceLoader(this.resourceLoader);
    }
    if (this.environment != null) {
       loader.setEnvironment(this.environment);
    }
    loader.load();
}

load方法中先是通过getBeanDefinitionRegistry方法获取了BeanDefinitionRegistry,因为当前应用上下文实际类型为AnnotationConfigServletWebServerApplicationContext,从类继承关系中可以找到该类实现了BeanDefinitionRegistry,所以getBeanDefinitionRegistry方法返回的就是当前应用上下文自身,如下

代码语言:javascript复制
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
    if (context instanceof BeanDefinitionRegistry) {
       return (BeanDefinitionRegistry) context;
    }
    if (context instanceof AbstractApplicationContext) {
       return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();
    }
    throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
}

然后创建了BeanDefinitionLoader,这里其实就新建了各种加载器

代码语言:javascript复制
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
    Assert.notNull(registry, "Registry must not be null");
    Assert.notEmpty(sources, "Sources must not be empty");
    this.sources = sources;
    this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
    this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
    this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
    this.scanner = new ClassPathBeanDefinitionScanner(registry);
    this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}

最后通过loader.load加载

代码语言:javascript复制
void load() {
    for (Object source : this.sources) {
       load(source);
    }
}

private void load(Object source) {
    Assert.notNull(source, "Source must not be null");
    if (source instanceof Class<?>) {
       load((Class<?>) source);
       return;
    }
    if (source instanceof Resource) {
       load((Resource) source);
       return;
    }
    if (source instanceof Package) {
       load((Package) source);
       return;
    }
    if (source instanceof CharSequence) {
       load((CharSequence) source);
       return;
    }
    throw new IllegalArgumentException("Invalid source type "   source.getClass());
}

由于source是一个class类型(启动类),所以走到load(Class<?> source)方法,如下

代码语言:javascript复制
private void load(Class<?> source) {
    if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
       // Any GroovyLoaders added in beans{} DSL can contribute beans here
       GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
       ((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
    }
    if (isEligible(source)) {
       this.annotatedReader.register(source);
    }
}

最终走到this.annotatedReader.register(source)方法,里面的方法就不跟进了,其实就只把启动类注册到registry中

listeners.contextLoaded(context),当load加载完之后最后发布一个ApplicationPreparedEvent事件

9 刷新IOC容器

来到最重要的流程,刷新IOC容器

代码语言:javascript复制
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
       StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

       // Prepare this context for refreshing.
       prepareRefresh();

       // Tell the subclass to refresh the internal bean factory.
       ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

       // Prepare the bean factory for use in this context.
       prepareBeanFactory(beanFactory);

       try {
          // Allows post-processing of the bean factory in context subclasses.
          postProcessBeanFactory(beanFactory);

          StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
          // Invoke factory processors registered as beans in the context.
          invokeBeanFactoryPostProcessors(beanFactory);

          // Register bean processors that intercept bean creation.
          registerBeanPostProcessors(beanFactory);
          beanPostProcess.end();

          // Initialize message source for this context.
          initMessageSource();

          // Initialize event multicaster for this context.
          initApplicationEventMulticaster();

          // Initialize other special beans in specific context subclasses.
          onRefresh();

          // Check for listener beans and register them.
          registerListeners();

          // Instantiate all remaining (non-lazy-init) singletons.
          finishBeanFactoryInitialization(beanFactory);

          // Last step: publish corresponding event.
          finishRefresh();
       }

       catch (BeansException ex) {
          if (logger.isWarnEnabled()) {
             logger.warn("Exception encountered during context initialization - "  
                   "cancelling refresh attempt: "   ex);
          }

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

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

          // Propagate exception to caller.
          throw ex;
       }

       finally {
          // Reset common introspection caches in Spring's core, since we
          // might not ever need metadata for singleton beans anymore...
          resetCommonCaches();
          contextRefresh.end();
       }
    }
}

同样依次看看每个步骤的逻辑

prepareRefresh(),刷新前的准备操作,如下

代码语言:javascript复制
protected void prepareRefresh() {
    // 设置active状态
    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());
       }
    }

    // 设置servletContext和servletConfig的source(如果有)
    initPropertySources();

    // 校验必填属性(默认没有,可以通过setRequiredProperties设置)
    getEnvironment().validateRequiredProperties();

    // 初始化earlyApplicationListeners 
    if (this.earlyApplicationListeners == null) {
       this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
       this.applicationListeners.clear();
       this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // 初始化earlyApplicationEvents 
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

obtainFreshBeanFactory(),获取BeanFactory,refreshBeanFactory()方法其实啥也没做,只是为BeanFactory设置了一个id

代码语言:javascript复制
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

prepareBeanFactory(beanFactory),准备BeanFactory

代码语言:javascript复制
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置ClassLoader
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置beanFactory表达式解析器,可以通过#beanName.xxxx来获取相关的属性或者调用相关的方法
    if (!shouldIgnoreSpel) {
       beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    }
    // 添加一个bean的属性转换器,比如属性是一个Object类型,但是在xml中是以字符串的形式配置的,
    // 就可以通过转换器互相转换
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 设置ApplicationContextAwareProcessor,它是一个BeanPostProcessor接口的实现,在Bean初始化之前
    // 设置各种Aware接口的实现,常用的ApplicationContextAware这些就是通过这个Processor来处理的
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 跳过以下接口的自动注入,因为这些是在ApplicationContextAwareProcessor中处理
    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);

    // 设置几个"自动装配"规则,如下:
    // 如果是 BeanFactory 的类,就注册 beanFactory
    // 如果是 ResourceLoader、ApplicationEventPublisher、ApplicationContext 等,
    // 就注入当前对象 this(applicationContext对象)
    // 此处 registerResolvableDependency() 会把它们加入到 DefaultListableBeanFactory 的 
    // resolvableDependencies 字段里面缓存,供后面处理依赖注入的时候使用,
    // DefaultListableBeanFactory#resolveDependency 处理依赖关系
    // 这也是为什么我们可以通过依赖注入的方式直接注入这几个对象,比如 ApplicationContext 可以直接依赖注入
    // 但是需要注意的是:这些 Bean,Spring 的 IOC 容器里其实是没有的。
    // beanFactory.getBeanDefinitionNames() 和 beanFactory.getSingletonNames() 都是找不到它们的,
    // 特别需要理解这一点
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 添加到ApplicationListenerDetector,它是一个BeanPostProcessor接口的实现,如果Bean实现了
    // ApplicationListener接口,则将其加入到当前applicationContext的applicationListeners列表
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 检查容器中是否包含名称为 loadTimeWeaver 的 bean,实际上是增加 Aspectj 的支持
    // AspectJ是一种静态代理技术,可以在编译期、编译后或者类加载期进行织入
    // 而类加载期织入简称为 LTW(Load Time Weaving),通过特殊的类加载器来代理 JVM 默认的类加载器实现
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
       // 添加 Bean 后置处理器:LoadTimeWeaverAwareProcessor
       // 在 Bean 初始化之前检查 Bean 是否实现了 LoadTimeWeaverAware 接口,如果是,
       // 则进行加载时织入
       beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
       // Set a temporary ClassLoader for type matching.
       beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册environment相关的Bean,比如environment、systemProperties、SystemEnvironment等
    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());
    }
}

postProcessBeanFactory(beanFactory),主要就是注册了一些servlet相关的BeanPostProcessor以及注册了servletContext、servletConfig等bean,这里basePackages和annotatedClasses都是空,所以不会执行scan和register

代码语言:javascript复制
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    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));
    }
}

invokeBeanFactoryPostProcessors(beanFactory),执行所有BeanFactoryPostProcessor的实现

代码语言:javascript复制
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    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.invokeBeanFactoryPostProcessors方法来执行,接着又是添加AspectJ的支持,上个步骤中已经添加过了,所有这里不会执行,先来看看getBeanFactoryPostProcessors()方法

代码语言:javascript复制
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
}

直接返回当前ApplicationContext的beanFactoryPostProcessors属性,下面来看看PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors,这个方法比较复杂,总的来说就是执行容器中所有实现了BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的类的方法,BeanDefinitionRegistryPostProcessor优于BeanFactoryPostProcessor执行,所以如果要加载自定义的BeanDefinition,这里是一个比较重要的扩展点,代码如下

代码语言:javascript复制
public static void invokeBeanFactoryPostProcessors(
       ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
    Set<String> processedBeans = new HashSet<>();
    if (beanFactory instanceof BeanDefinitionRegistry) {
       BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
       List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
       List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
       // 这里拿到的beanFactoryPostProcessors有第三个,分别是
       // CachingMetadataReaderFactoryPostProcessor
       // ConfigurationWarningsPostProcessor
       // PropertySourceOrderingBeanFactoryPostProcessor
       // 先将实现了BeanDefinitionRegistryPostProcessor接口的Processor挑出来执行
       // 其他的加入regularPostProcessors待执行
       for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
          if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
             BeanDefinitionRegistryPostProcessor registryProcessor =
                   (BeanDefinitionRegistryPostProcessor) postProcessor;
             // CachingMetadataReaderFactoryPostProcessor注册了一个SharedMetadataReaderFactoryBean
             // ConfigurationWarningsPostProcessor打印了一些警告信息
             registryProcessor.postProcessBeanDefinitionRegistry(registry);
             registryProcessors.add(registryProcessor);
          }
          else {
             // PropertySourceOrderingBeanFactoryPostProcessor添加到regularPostProcessors待执行
             regularPostProcessors.add(postProcessor);
          }
       }

       
       List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

       // 从beanFactory中获取注册了的实现了BeanDefinitionRegistryPostProcessor接口的beanName
       // 并且从中挑选出实现了PriorityOrdered接口的Bean加入到currentRegistryProcessors
       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);
          }
       }
       // 对currentRegistryProcessors排序
       sortPostProcessors(currentRegistryProcessors, beanFactory);
       registryProcessors.addAll(currentRegistryProcessors);
       // 执行currentRegistryProcessors,这里拿到的processor只有一个就是ConfigurationClassPostProcessor
       // 这个processor非常重要,加载了所有的Bean(@Controller, @Service,@Configuration等等)
       invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
       // 清除currentRegistryProcessors
       currentRegistryProcessors.clear();

       // 再从beanFactory中获取注册了的实现了BeanDefinitionRegistryPostProcessor接口的beanName
       // 并且从中挑选出实现了Ordered接口的Bean加入到currentRegistryProcessors
       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);
          }
       }
       // 执行实现了Ordered接口的BeanDefinitionRegistryPostProcessor,默认没有
       sortPostProcessors(currentRegistryProcessors, beanFactory);
       registryProcessors.addAll(currentRegistryProcessors);
       invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
       currentRegistryProcessors.clear();

       // 最后循环从beanFactory中获取注册了的实现了BeanDefinitionRegistryPostProcessor接口的beanName
       // 然后依次执行其postProcessBeanDefinitionRegistry方法
       // 直到没有新的BeanDefinitionRegistryPostProcessor出现
       // 假如用了mybatis,这其中就包括了mybatis的Mapper扫描
       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();
       }

       // 最后再去执行所有processor的postProcessBeanFactory方法
       // 实现了BeanDefinitionRegistryPostProcessor接口的先执行
       // BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的一个子接口
       // 所以实现了BeanDefinitionRegistryPostProcessor接口必然要实现BeanFactoryPostProcessor接口
       invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
       invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
       // Invoke factory processors registered with the context instance.
       invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 最后再找到所有实现了BeanFactoryPostProcessor接口的Bean,并且按照PriorityOrdered,Ordered以及没有
    // 排序的分开依次执行其postProcessBeanFactory方法
    String[] postProcessorNames =
          beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
       if (processedBeans.contains(ppName)) {
          // skip - already processed in first phase above
       }
       else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
          priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
       }
       else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
          orderedPostProcessorNames.add(ppName);
       }
       else {
          nonOrderedPostProcessorNames.add(ppName);
       }
    }

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

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

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

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

由于文章字数限制,后续分析请看Spring系列二之springboot启动(下)

0 人点赞