SpringBoot源码解析(四)初始化IOC容器

685 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情

public ConfigurableApplicationContext run(String... args) {
   //1 创建StopWatch对象
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
   //2 设置Headless模式
   configureHeadlessProperty();
   //3 创建事件发布器
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.starting();
   try {
      // 将main方法的args参数封装到一个对象中
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      //4 准备容器环境信息
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      configureIgnoreBeanInfo(environment);
      //5.打印Banner
      Banner printedBanner = printBanner(environment);
      //6.创建IOC容器和Bean工厂
      context = createApplicationContext();
      //7.初始化异常报告器
      exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
      //8.初始化IOC容器
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      listeners.started(context);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

进入第八步,初始化IOC容器

八、初始化IOC容器

private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
   //设置容器运行环境
   context.setEnvironment(environment);
   //8.1 后置处理器处理IOC容器
   postProcessApplicationContext(context);
   //8.2 初始化容器
   applyInitializers(context);
   //8.3 发布容器初始化事件
   listeners.contextPrepared(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 DefaultListableBeanFactory) {
      ((DefaultListableBeanFactory) beanFactory)
            .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
   //8.4注册主启动类
   load(context, sources.toArray(new Object[0]));
   //8.5发布容器准备就绪事件
   listeners.contextLoaded(context);
}

8.1 后置处理器处理IOC容器

protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
   //8.1.1 如果BeanName生成器不为空则注册BeanName生成器
   if (this.beanNameGenerator != null) {
      context.getBeanFactory().registerSingleton(
            AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
            this.beanNameGenerator);
   }
   //8.1.2 如果资源加载器不为空则设置资源加载器和类加载器
   if (this.resourceLoader != null) {
      if (context instanceof GenericApplicationContext) {
         ((GenericApplicationContext) context)
               .setResourceLoader(this.resourceLoader);
      }
      if (context instanceof DefaultResourceLoader) {
         ((DefaultResourceLoader) context)
               .setClassLoader(this.resourceLoader.getClassLoader());
      }
   }
   //8.1.3 如果类型转换器不为空则设置类型转换器
   if (this.addConversionService) {
      context.getBeanFactory().setConversionService(
            ApplicationConversionService.getSharedInstance());
   }
}
  • BeanName生成器 生成Bean名称
  • resourceLoader资源加载器 通过url加载各种资源(xml,text等)
  • conversionService类型转换器 将配置转换成对应类型

这里只会向IOC容器中注入类型转换器(在第4步准备容器环境信息时创建的)

8.2 初始化容器

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

获取所有初始化器,执行初始化方法

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

这里的初始化器是在SpringApplication构造器的第2步设置进来的,通过Sping的SPI机制创建了META-INF/spring.factories下所有的ApplicationContextInitializer实现类

8.3 发布容器初始化事件

发布容器初始化事件: ApplicationContextInitializedEvent

@Override
public void contextPrepared(ConfigurableApplicationContext context) {
   this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
         this.application, this.args, context));
}

8.4 注册主启动类

protected void load(ApplicationContext context, Object[] sources) {
   if (logger.isDebugEnabled()) {
      logger.debug(
            "Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
   }
   //8.4.1创建BeanDefinition解析器
   BeanDefinitionLoader loader = createBeanDefinitionLoader(
         getBeanDefinitionRegistry(context), sources);
   //设置Bean命名器
   if (this.beanNameGenerator != null) {
      loader.setBeanNameGenerator(this.beanNameGenerator);
   }
   //设置资源加载器
   if (this.resourceLoader != null) {
      loader.setResourceLoader(this.resourceLoader);
   }
   //设置环境
   if (this.environment != null) {
      loader.setEnvironment(this.environment);
   }
   //8.4.2 加载源信息到注册器中
   loader.load();
}

8.4.1 创建BeanDefinition解析器

这里首先会先获取注册器,因为SpringBoot创建的IOC容器本身就继承了注册器(BeanDefinitionRegistry)功能,所以会直接将创建的IOC容器返回

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

sources就是构造器时通过栈获取到的启动类,然后直接创建了一个BeanDefinition加载器

protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
   return new BeanDefinitionLoader(registry, sources);
}

在构造器中创建了用于BeanDefinition解析的组件

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);
   //xml读取器
   this.xmlReader = new XmlBeanDefinitionReader(registry);
   if (isGroovyPresent()) {
      this.groovyReader = new GroovyBeanDefinitionReader(registry);
   }
   //类路径下的Bean定义扫描器
   this.scanner = new ClassPathBeanDefinitionScanner(registry);
   //类过滤器
   this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}

8.4.2 加载源信息到注册器

将数据源(启动类)解析并加载到注册器中(SpringBoot的IOC容器)

public int load() {
   int count = 0;
   //sources为启动类
   for (Object source : this.sources) {
      count += load(source);
   }
   return count;
}

source为启动类,所以是Class类型

private int load(Object source) {
   Assert.notNull(source, "Source must not be null");
   //如果class类
   if (source instanceof Class<?>) {
      return load((Class<?>) source);
   }
   //如果是资源类
   if (source instanceof Resource) {
      return load((Resource) source);
   }
   //如果是Package
   if (source instanceof Package) {
      return load((Package) source);
   }
   //如果是字符
   if (source instanceof CharSequence) {
      return load((CharSequence) source);
   }
   throw new IllegalArgumentException("Invalid source type " + source.getClass());
}

启动类被@SpringBootApplication标注

@SpringBootApplication继承了@SpringBootConfiguration,

@SpringBootConfiguration继承了@Configuration

@Configuration继承了@Component注解

所以启动类会被annotatedReader解析

private int 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);
      load(loader);
   }
   //如果含有@Component注解
   if (isComponent(source)) {
      this.annotatedReader.register(source);
      return 1;
   }
   return 0;
}

最后会被spring的注解解析将启动类解析成BeanDefinition到注册器中(SpringBoot的IOC容器继承了注册器)

<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
                            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

        // 包装为BeanDefinition
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        abd.setInstanceSupplier(instanceSupplier);
        // 解析Scope信息,决定作用域
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        abd.setScope(scopeMetadata.getScopeName());
        // 生成Bean的名称
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        // 解析BeanDefinition的注解
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }
        // 使用定制器修改这个BeanDefinition
        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }

        // 使用BeanDefinitionHolder,将BeanDefinition注册到IOC容器中
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

8.5 发布容器准备就绪事件

将监听器添加容器中,发布容器准备就绪事件ApplicationPreparedEvent

public void contextLoaded(ConfigurableApplicationContext context) {
   for (ApplicationListener<?> listener : this.application.getListeners()) {
      if (listener instanceof ApplicationContextAware) {
         ((ApplicationContextAware) listener).setApplicationContext(context);
      }
      context.addApplicationListener(listener);
   }
   this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}

总结

  1. 发布容器初始化事件: ApplicationContextInitializedEvent
  2. 创建BeanDefinition解析器并且将启动类加载到注册器中
  3. 发布容器准备就绪事件ApplicationPreparedEvent