前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring系列一之springboot启动(上)

Spring系列一之springboot启动(上)

原创
作者头像
用户9511949
发布2024-08-01 17:57:07
780
发布2024-08-01 17:57:07

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的生命周期就结束了

BootstrapContext
BootstrapContext
PrepareContext
PrepareContext

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

PropertyAndMethod
PropertyAndMethod

持有两个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

EventPublishingRunListener
EventPublishingRunListener

获取到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.properties
application.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,如下

BasicBeanDefinition
BasicBeanDefinition

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之后打印一些启动信息,如下

StartupInfo
StartupInfo

之后就是注册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启动(下)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 整体流程
  • 2 DefaultBootstrapContext
  • 3 Headless配置
  • 4 SpringApplicationRunListeners
  • 5 PrepareEnvironment
  • 6 是否忽略BeanInfo类的搜索
  • 7 创建ApplicationContext
  • 8 初始化IOC容器
  • 9 刷新IOC容器
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档