Spring Boot源码解析(三)创建ApplicationContext

接上文(),我们已经介绍了部分SpringApplication的启动过程,今天我们将继续讲解如何创建ApplicationContext的过程。

介绍

/**
 * 这里我们可以自定义创建过程来覆盖缺省的Context
 */
protected ConfigurableApplicationContext createApplicationContext() {
    return this.applicationContextFactory.create(this.webApplicationType);
}

Spring Boot创建ApplicationContext的过程主要为了后面准备和刷新Context,当然我们可以定制这个创建过程,这里我们先介绍Spring Boot的缺省逻辑

static class Factory implements ApplicationContextFactory {
    @Override
    public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
        // 创建并返回一个AnnotationConfigServletWebServerApplicationContext
	return (webApplicationType != WebApplicationType.SERVLET) ? null
		: new AnnotationConfigServletWebServerApplicationContext();
    }
}

static class Factory implements ApplicationContextFactory {

    @Override
    public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
        // 创建并返回一个AnnotationConfigReactiveWebServerApplicationContext
	return (webApplicationType != WebApplicationType.REACTIVE) ? null
		: new AnnotationConfigReactiveWebServerApplicationContext();
    }
}

这里会根据应用的类型创建不同的ApplicationContext ,下面我们将主要讲解servlet类型的ApplicationContext,关于Reactive Web Application的部分将在以后单独讲解。

/**
 * 创建AnnotationConfigServletWebServerApplicationContext
 */
public AnnotationConfigServletWebServerApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

从上面的代码可以看出创建ApplicationContext的过程主要有两部分,我们将逐一讲解。

创建AnnotatedBeanDefinitionReader

/**
 * 创建一个新的AnnotatedBeanDefinitionReader,如果这个registry是EnvironmentCapable的子类,
 * 比如是一个ApplicationContext,那么Environment将从这个ApplicationContext继承
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}

这里的registry就是AnnotationConfigServletWebServerApplicationContext本身, 因为AnnotationConfigServletWebServerApplicationContext是新创建的,所有getOrCreateEnvironment(registry)返回的一定是一个新的StandardEnvironment。而将之前创建的Environment注入到这里是在准备ApplicationContext阶段进行的。

 /**
 * 用registry和environment来创建一个新的AnnotatedBeanDefinitionReader
 */
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;

    // 推断ApplicationContext所需要的BeanFactory,Classloader等
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);

    // 注册annotation postprocessor
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

创建AnnotatedBeanDefinitionReader实例的构造方法一共有2行逻辑, 首先会根据registry创建BeanFactory,Classloader等,然后给registry也就是ApplicationContext注册所有相关的annotation postprocessor,下面我们先来看看如果推断出BeanFactory和各种loader的

创建ConditionEvaluator

public ConditionContextImpl(@Nullable BeanDefinitionRegistry registry,
    @Nullable Environment environment, @Nullable ResourceLoader resourceLoader) {
    this.registry = registry;
    // 推断哪种beanFactory
    this.beanFactory = deduceBeanFactory(registry);
    // 推断哪种environment
    this.environment = (environment != null ? environment : deduceEnvironment(registry));
    // 推断哪种resourceLoader
    this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));
    // 推断哪种classLoader
    this.classLoader = deduceClassLoader(resourceLoader, this.beanFactory);
}
  • beanFactory: 根据registry的类型推断出哪种beanFactory,前面我们已经提到registry就是AnnotationConfigServletWebServerApplicationContext,而AnnotationConfigServletWebServerApplicationContextConfigurableApplicationContext的子类,所以最后得到的是DefaultListableBeanFactory
  • environment:前面我们已经得到了一个新的StandardEnvironment,这里直接设置 ​​​​​​​
  • resourceLoader:这里和environment类似,因为AnnotationConfigServletWebServerApplicationContext本身就是ResourceLoader的子类,所以返回的就是它本身
  • classLoader: 将返回beanFactory上的beanClassLoader

注册annotation后处理器

下面是如何注册annotation postprocessor,整个过程看上去较为复杂,实际逻辑并不复杂,只是注册不同类型的postprocessor

/**
 * 注册所有相关的注解后处理器annotation postprocessor
 */
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
		BeanDefinitionRegistry registry, @Nullable Object source) {

    // 返回registry上的DefaultListableBeanFactory
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
	if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 设置DependencyComparator
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
	}
	if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // 设置AutowireCandidateResolver
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
	}
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    // 创建一个可以处理有@Configuration注解的类的postprocessor,并注册到RootBeanDefinition
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
	RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 创建一个可以处理有@Autowired注解的类的postprocessor,并注册到RootBeanDefinition
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
	RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 创建一个可以处理有一般类型注解的类的postprocessor,并注册到RootBeanDefinition
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
	RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 创建一个可以处理有@Persistence注解的类的postprocessor,并注册到RootBeanDefinition
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
	RootBeanDefinition def = new RootBeanDefinition();
	try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
		AnnotationConfigUtils.class.getClassLoader()));
	    }
	catch (ClassNotFoundException ex) {
		throw new IllegalStateException(
		"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
	}
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 创建一个可以处理eventlistener的postprocessor,并注册到RootBeanDefinition
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
	RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    // 创建一个可以处理有@Eventlistener注解的类的postprocessor,并注册到RootBeanDefinition
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
	RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
	def.setSource(source);
	beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

创建ClassPathBeanDefinitionScanner

创建类扫描器ClassPathBeanDefinitionScannerClassPathBeanDefinitionScanner会对指定路径下的所有class进行扫描,将符合条件的转成BeanDefinition并注册到ApplicationContext中,这部分会在以后的文章中讲解,下面我们先来看一下如何创建一个ClassPathBeanDefinitionScanner。

/**
 * 创建一个新的ClassPathBeanDefinitionScanner
 */
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
	Environment environment, @Nullable ResourceLoader resourceLoader) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;

    // 定义扫描过滤器
    if (useDefaultFilters) {
	registerDefaultFilters();
    }

    // 设置环境
    setEnvironment(environment);
    // 设置resourceLoader
    setResourceLoader(resourceLoader);
}

注册缺省过滤器

首先我们会先注册一个缺省的过滤器Filter,缺省的Filter会检查所有有以下几种注解的类

  • @Component
  • @Repository
  • @Service
  • @Controller
  • @ManagedBean
  • @Named
protected void registerDefaultFilters() {
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
	this.includeFilters.add(new AnnotationTypeFilter(
		((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
	logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
    // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
	this.includeFilters.add(new AnnotationTypeFilter(
		((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
		logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
    // JSR-330 API not available - simply skip.
    }
}

`this.includeFilters.add(newAnnotationTypeFilter(Component.class));这段代码看上去去只加了Component注解,实际上它会找到所有有Component注解的注解,如Repository,Service,Controller

设置Environment

这里Environment的作用是,当有条件注解或者有占位符注解的component类时,可以用Environment里的变量来替代

/**
 * 设置Environment
 */
public void setEnvironment(Environment environment) {
    Assert.notNull(environment, "Environment must not be null");
    this.environment = environment;
    this.conditionEvaluator = null;
}

设置ResourceLoader

设置ResourceLoader是为了后面处理需要加载各种properties里的变量时使用

public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
    this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
    this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
    this.componentsIndex = CandidateComponentsIndexLoader.loadIndex(this.resourcePatternResolver.getClassLoader());
}

结语

我们已经讲完了所有创建ApplicationContext的步骤,这里其实是创建了一个AnnotationConfigServletWebServerApplicationContext,后续文章将继续讲解初始化SpringApplication过程中的其他步骤,包括准备,刷新Context和启动Runner的部分。

系列文章入口

Spring Boot源码解析(一)SpringApplication初始化

Spring Boot源码解析(二)启动加载过程


版权声明:本文为xchann原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。