springboot源码-AnnotationConfigServletWebServerApplicationContext

/*
 * Copyright 2012-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.web.servlet.context;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigRegistry;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.AnnotationScopeMetadataResolver;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScopeMetadataResolver;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * {@link ServletWebServerApplicationContext} 接受带注释的类作为输入 - 在
 * 特定的 {@link org.springframework.context.annotation.Configuration @Configuration}
 * - 带注释的类,还有普通的 {@link Component @Component} 类和 JSR-330
 * 使用 {@code javax.inject} 注释的兼容类。允许注册
 * 一个一个的类(指定类名作为配置位置)以及类路径
 * 扫描(指定基本包作为配置位置)。
 * <p>
 * 注意:如果有多个 {@code @Configuration} 类,后面的 {@code @Bean}
 * 定义将覆盖先前加载的文件中定义的定义。这可以利用
 * 通过额外的 Configuration 类故意覆盖某些 bean 定义。
 *
 * @author Phillip Webb
 * @see #register(Class...)
 * @see #scan(String...)
 * @see ServletWebServerApplicationContext
 * @see AnnotationConfigServletWebApplicationContext
 * @since 1.0.0
 */
public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext
		implements AnnotationConfigRegistry {

	private final AnnotatedBeanDefinitionReader reader;

	private final ClassPathBeanDefinitionScanner scanner;

	private final Set<Class<?>> annotatedClasses = new LinkedHashSet<>();

	private String[] basePackages;

	/**
	 * 创建一个新的 {@link AnnotationConfigServletWebServerApplicationContext} 需要
	 * 通过 {@link #register} 调用填充,然后手动填充
	 * {@linkplain #refresh refreshed}.
	 */
	public AnnotationConfigServletWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * 创建一个新的 {@link AnnotationConfigServletWebServerApplicationContext}
	 * 给定 {@code DefaultListableBeanFactory}。上下文需要通过
	 * {@link #register} 调用然后手动{@linkplain #refresh refreshed}。
	 *
	 * @param beanFactory 用于此上下文的 DefaultListableBeanFactory 实例
	 */
	public AnnotationConfigServletWebServerApplicationContext(DefaultListableBeanFactory beanFactory) {
		super(beanFactory);
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

	/**
	 * 创建一个新的 {@link AnnotationConfigServletWebServerApplicationContext},派生
	 * 来自给定注释类的 bean 定义并自动刷新
	 * 语境。
	 *
	 * @param annotatedClasses one or more annotated classes, e.g. {@code @Configuration}
	 *                         classes
	 */
	public AnnotationConfigServletWebServerApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}

	/**
	 * 新建一个{@link AnnotationConfigServletWebServerApplicationContext},扫描
	 * 用于给定包中的 bean 定义并自动刷新
	 * 语境。
	 *
	 * @param basePackages the packages to check for annotated classes
	 */
	public AnnotationConfigServletWebServerApplicationContext(String... basePackages) {
		this();
		scan(basePackages);
		refresh();
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * 将给定的环境委托给底层 {@link AnnotatedBeanDefinitionReader} 和
	 * {@link ClassPathBeanDefinitionScanner} 成员。
	 */
	@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		super.setEnvironment(environment);
		this.reader.setEnvironment(environment);
		this.scanner.setEnvironment(environment);
	}

	/**
	 * 提供自定义 {@link BeanNameGenerator} 以用于
	 * {@link AnnotatedBeanDefinitionReader} 和/或
	 * {@link ClassPathBeanDefinitionScanner},如果有的话。
	 * <p>
	 * 默认为
	 * {@link org.springframework.context.annotation.AnnotationBeanNameGenerator}。
	 * <p>
	 * 对该方法的任何调用都必须在调用 {@link #register(Class...)} 之前发生
	 * 和/或 {@link #scan(String...)}。
	 *
	 * @param beanNameGenerator the bean name generator
	 * @see AnnotatedBeanDefinitionReader#setBeanNameGenerator
	 * @see ClassPathBeanDefinitionScanner#setBeanNameGenerator
	 */
	public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
		this.reader.setBeanNameGenerator(beanNameGenerator);
		this.scanner.setBeanNameGenerator(beanNameGenerator);
		this.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
				beanNameGenerator);
	}

	/**
	 * 设置 {@link ScopeMetadataResolver} 以用于检测到的 bean 类。
	 * <p>
	 * 默认值为 {@link AnnotationScopeMetadataResolver}。
	 * <p>
	 * 对该方法的任何调用都必须在调用 {@link #register(Class...)} 之前发生
	 * 和/或 {@link #scan(String...)}。
	 *
	 * @param scopeMetadataResolver the scope metadata resolver
	 */
	public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
		this.reader.setScopeMetadataResolver(scopeMetadataResolver);
		this.scanner.setScopeMetadataResolver(scopeMetadataResolver);
	}

	/**
	 * 注册一个或多个要处理的带注释的类。注意
	 * {@link #refresh()} 必须被调用才能让上下文完全处理新的
	 * 班级。
	 * <p>
	 * 调用 {@code #register} 是幂等的;添加更多相同的注释类
	 * 不止一次没有额外效果。
	 *
	 * @param annotatedClasses one or more annotated classes, e.g. {@code @Configuration}
	 *                         classes
	 * @see #scan(String...)
	 * @see #refresh()
	 */
	@Override
	public final void register(Class<?>... annotatedClasses) {
		Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
		this.annotatedClasses.addAll(Arrays.asList(annotatedClasses));
	}

	/**
	 * 在指定的基本包内执行扫描。请注意 {@link #refresh()}
	 * 必须被调用,以便上下文完全处理新类。
	 *
	 * @param basePackages the packages to check for annotated classes
	 * @see #register(Class...)
	 * @see #refresh()
	 */
	@Override
	public final void scan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		this.basePackages = basePackages;
	}

	@Override
	protected void prepareRefresh() {
		this.scanner.clearCache();
		super.prepareRefresh();
	}

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

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouD_dm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值