深入SpringBoot源码(十三)context.setEnvironment

这章我们开始学习SpringApplication对ApplicationContext的相关操作,ApplicationContext的prepare与refresh可以算是SpringApplication的最重要部分。
在这里插入图片描述
SpringApplication的prepareContext方法:

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

在这里插入图片描述
由于我的应用引入了spring-boot-starter-webflux依赖,所以这里的context类型为AnnotationConfigReactiveWebServerApplicationContext,environment类型为ApplicationReactiveWebEnvironment。AnnotationConfigReactiveWebServerApplicationContext的setEnvironment方法源码:

	public void setEnvironment(ConfigurableEnvironment environment) {
		super.setEnvironment(environment);
		this.reader.setEnvironment(environment);
		this.scanner.setEnvironment(environment);
	}

super.setEnvironment(environment)调用的是AbstractApplicationContext的setEnvironment方法:

	public void setEnvironment(ConfigurableEnvironment environment) {
		this.environment = environment;
	}

AnnotationConfigReactiveWebServerApplicationContext的成员字段reader和scanner在构造方法被调用时进行赋值:

	public AnnotationConfigReactiveWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

AnnotatedBeanDefinitionReader是方便的适配器,用于bean类的编程注册。其构造方法如下:

	/**
	 * 为给定的注册表创建一个新的AnnotatedBeanDefinitionReader。
	 * 如果注册表是EnvironmentCapable,例如是ApplicationContext,则将继承Environment,否则将创建并使用新的StandardEnvironment。
	 * @param registry 以BeanDefinitionRegistry的形式将bean定义加载到其中的BeanFactory
	 */
	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}

	/**
	 * 使用给定的Environment为给定的注册表创建一个新的AnnotatedBeanDefinitionReader 。
	 * @param registry 以BeanDefinitionRegistry的形式将bean定义加载到其中的BeanFactory
	 * @param environment 评估bean定义配置文件时使用的Environment 。
	 * @since 3.1
	 */
	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);
	}

	/**
	 * 如果可以,从给定的BeanDefinitionRegistry中获取环境,否则返回一个新的标准环境。
	 */
	private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		if (registry instanceof EnvironmentCapable) {
			return ((EnvironmentCapable) registry).getEnvironment();
		}
		return new StandardEnvironment();
	}

ClassPathBeanDefinitionScanner是一个bean定义扫描器,它检测类路径上的候选bean,使用给定的注册表(BeanFactory或ApplicationContext)注册相应的bean定义。ClassPathBeanDefinitionScanner通过可配置的类型过滤器检测候选类,默认过滤器包括使用 Spring 的@Component 、 @Repository 、 @Service或@Controller原型注解的类。其构造方法的源码如下:

	/**
	 * 为给定的bean工厂创建一个新的ClassPathBeanDefinitionScanner 。
	 * @param registry 以BeanDefinitionRegistry的形式将 bean 定义加载到其中的BeanFactory
	 */
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
		this(registry, true);
	}

	/**
	 * 为给定的 bean 工厂创建一个新的ClassPathBeanDefinitionScanner 。
	 * 如果传入的 bean factory 不仅实现了BeanDefinitionRegistry接口,还实现了ResourceLoader接口,那么它也会被用作默认的ResourceLoader 。
	 * 这通常是org.springframework.context.ApplicationContext实现的情况。
	 * 如果给定一个普通的BeanDefinitionRegistry ,默认的ResourceLoader将是一个org.springframework.core.io.support.PathMatchingResourcePatternResolver 。
	 * 如果传入的 bean 工厂也实现了EnvironmentCapable它的环境将被这个读者使用。否则,阅读器将初始化并使用StandardEnvironment 。
	 * 所有ApplicationContext实现都是EnvironmentCapable ,而普通的BeanFactory实现不是。
	 * @param registry 以BeanDefinitionRegistry的形式将 bean 定义加载到其中的BeanFactory
	 * @param useDefaultFilters 是否包含@Component 、 @Repository 、 @Service和@Controller原型注解的默认过滤器
	 */
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
		this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
	}

	/**
	 * 为给定的 bean 工厂创建一个新的ClassPathBeanDefinitionScanner ,并在评估 bean 定义配置文件元数据时使用给定的Environment 。
	 * 如果传入的 bean factory 不仅实现了BeanDefinitionRegistry接口,还实现了ResourceLoader接口,那么它也会被用作默认的ResourceLoader 。这通常是org.springframework.context.ApplicationContext实现的情况。
	 * 如果给定一个普通的BeanDefinitionRegistry ,默认的ResourceLoader将是一个org.springframework.core.io.support.PathMatchingResourcePatternResolver 。
	 * @param registry 以BeanDefinitionRegistry的形式将 bean 定义加载到其中的BeanFactory
	 * @param useDefaultFilters 是否包含@Component 、 @Repository 、 @Service和@Controller原型注解的默认过滤器
	 * @param environment 评估 bean 定义配置文件元数据时使用的 Spring Environment
	 */
	public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment) {

		this(registry, useDefaultFilters, environment,
				(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
	}

	/**
	 * 为给定的 bean 工厂创建一个新的ClassPathBeanDefinitionScanner ,并在评估 bean 定义配置文件元数据时使用给定的Environment 。
	 * @param registry 以BeanDefinitionRegistry的形式将 bean 定义加载到其中的BeanFactory
	 * @param useDefaultFilters 是否包含@Component 、 @Repository 、 @Service和@Controller原型注解的默认过滤器
	 * @param environment 评估 bean 定义配置文件元数据时使用的 Spring Environment
	 * @param resourceLoader 要使用的ResourceLoader
	 */
	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);
		setResourceLoader(resourceLoader);
	}

	private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		if (registry instanceof EnvironmentCapable) {
			return ((EnvironmentCapable) registry).getEnvironment();
		}
		return new StandardEnvironment();
	}

	/**
	 * 在解析占位符和评估@Conditional组件类时设置要使用的环境。默认值为StandardEnvironment 。
	 */
	public void setEnvironment(Environment environment) {
		Assert.notNull(environment, "Environment must not be null");
		this.environment = environment;
		this.conditionEvaluator = null;
	}

	/**
	 * 设置ResourceLoader以用于资源位置。这通常是ResourcePatternResolver实现。默认是PathMatchingResourcePatternResolver ,也能够通过ResourcePatternResolver接口解析资源模式。
	 */
	@Override
	public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
		this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
		this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
		this.componentsIndex = CandidateComponentsIndexLoader.loadIndex(this.resourcePatternResolver.getClassLoader());
	}

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值