sprigboot 自动配置 启动
Springboot
springboot 2.7.10
自动配置
@SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {
@Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}),
@Filter(type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})}
)
@SpringBootApplication
@SpringBootConfiguration
@Configuration
spring 注解,用于定义配置类,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器
@Indexed
加快springboot的启动速度
@EnableAutoConfiguration
启用自动配置
@AutoConfigurationPackage
AutoConfigurationPackages.Registrar.class 注入到容器中
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
- AutoConfigurationPackages.Registrar.class
注入后由其他调用 registerBeanDefinitions
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(
registry,
(String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0])
);
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
- 方法register
将AutoConfigurationPackages这个类注入到容器中
private static final String BEAN = AutoConfigurationPackages.class.getName();
//org.springframework.boot.autoconfigure.AutoConfigurationPackages
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
BasePackagesBeanDefinition beanDefinition =
(BasePackagesBeanDefinition)registry.getBeanDefinition(BEAN);
beanDefinition.addBasePackages(packageNames);
} else {
registry.registerBeanDefinition(BEAN, new BasePackagesBeanDefinition(packageNames));
}
- BasePackagesBeanDefinition 添加扫描基础包(springboot注解所在的包)
addBasePackages(basePackages);
static final class BasePackagesBeanDefinition extends GenericBeanDefinition {
private final Set<String> basePackages = new LinkedHashSet<>();
BasePackagesBeanDefinition(String... basePackages) {
setBeanClass(BasePackages.class);
setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
addBasePackages(basePackages);
}
}
@Import({AutoConfigurationImportSelector.class})
public class AutoConfigurationImportSelector implements
DeferredImportSelector,
/**
Spring 容器在初始化主动检测当前 bean 是否实现了 Aware 接口,如果实现了则回调其 set 方法将相应的参数设置给该 bean ,这个时候该 bean 就从 Spring 容器中取得相应的资源。
*/
BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware,
//执行优先级
Ordered {
}
- DeferredImportSelector
public interface DeferredImportSelector extends ImportSelector {
@Nullable
default Class<? extends Group> getImportGroup() {
return null;
}
interface Group {
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
Iterable<Entry> selectImports();
class Entry {
private final AnnotationMetadata metadata;
private final String importClassName;
public Entry(AnnotationMetadata metadata, String importClassName) {
this.metadata = metadata;
this.importClassName = importClassName;
}
public AnnotationMetadata getMetadata() {
return this.metadata;
}
public String getImportClassName() {
return this.importClassName;
}
}
}
}
- process()
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
AutoConfigurationEntry autoConfigurationEntry =
((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
- getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
//获取注解的attribute exclude excludeName
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取自动配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//删除重复项
configurations = removeDuplicates(configurations);
//获取要除去的
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//删除排除项
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
//过滤
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
- getCandidateConfigurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
//读取 META-INF/spring.factories
List<String> configurations =
new ArrayList<>(SpringFactoriesLoader.
loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
//读取 META-INF/spring/%s.imports
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
.forEach(configurations::add);
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
-
SpringFactoriesLoader.loadFactoryNames()
兼容老版本的 META-INF/spring.factories
适配springboot2.7.0以下
# springboot2.6.13 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ ............
-
ImportCandidates.load
2.7.0新版本读取 META-INF/spring/%s.imports
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
String location = String.format(LOCATION, annotation.getName());
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
List<String> importCandidates = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
importCandidates.addAll(readCandidateConfigurations(url));
}
return new ImportCandidates(importCandidates);
}
@ComponentScan
组件包扫描
启动过程
@SpringBootApplication
public class SourcecodeApplication {
public static void main(String[] args) {
SpringApplication.run(SourcecodeApplication.class, args);
}
}
-
跟进run()
可以发现又调用了新的run()
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
-
跟进run()
这个方法主要做了两件事
- 创建SpringApplication实例
- 执行实例的run()方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
创建SpringApplication实例
- 调用其他构造方法
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
- 跟进
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//初始化resourceLoader
this.resourceLoader = resourceLoader;
//断言 primarySources不为空
Assert.notNull(primarySources, "PrimarySources must not be null");
// primarySources 的变量提升
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
/**
判断应用的类型
- NONE
- SERVLET
- REACTIVE
*/
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//获取 BootstrapRegistryInitializer 类型的参数集合
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
// 获取所有的 ApplicationContextInitializer 实例
setInitializers((Colection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 获取所有监听器实例
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//确定应用程序的主类
this.mainApplicationClass = deduceMainApplicationClass();
}
- WebApplicationType.deduceFromClasspath()
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
- getSpringFactoriesInstances
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// 获取spring.fatories
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 实例化类
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
运行示例run
public ConfigurableApplicationContext run(String... args) {
// 启动计时
long startime = System.nanoTime();
// 创建一个引导类的上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
//ioc 容器声明
ConfigurableApplicationContext context = null;
// 用于配置是否运行在无头模式 headless mode
configureHeadlessProperty();
// 获取监听器列表
SpringApplicationRunListeners listeners = getRunListeners(args);
// 启动监听器
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
//创建一个 ApplicationArguments 对象,表示应用程序启动时的命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备应用程序的环境,包括加载配置文件、解析命令行参数等。
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
// 配置是否忽略 JavaBean 的信息
configureIgnoreBeanInfo(environment);
// 打印Banner,
Banner printedBanner = printBanner(environment);
// 创建应用程序上下文对象
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 配置context的基本信息
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
/**
刷新context
里面包括了spring 容器的qidong
springboot自动配置
初始化web容器
*/
refreshContext(context);
// 刷新的后置处理
afterRefresh(context, applicationArguments);
//打印运行时间
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 发布监听应用并启动事件
listeners.started(context, timeTakenToStartup);
// 执行runners (回调)初始化参数
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
}
catch (Throwable ex) {
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
return context;
}