/*
* 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));
}
}
}
springboot源码-AnnotationConfigServletWebServerApplicationContext
最新推荐文章于 2022-10-04 20:45:45 发布