1、一个注解@SpringBootApplication
是一个组合注解,由3个注解构成
1.1 @SpringBootConfiguration
- 底层就是一个@Configuration,表示当前引导类就是一个配置类
1.2 @ComponentScan
- 组件扫描,表示当前引导类所在的包及子包下的注解能够被Spring识别
1.3 @EnableAutoConfiguration
是一个组合注解,由2个注解构成
- @AutoConfigurationPackage【了解】
- 底层就是一个@import注解,导入Registrar类,该类会自动去调用registerBeanDefinitions方法,该方法中能够获取到引导类所在的包,配置@ComponentScan就可以让SpringBoot去扫描引导类包下的组件
- @Import
- 该注解导入一个
AutoConfigurationImportSelector
类,该类会自动调用selectImports
方法,方法内部会调用getAutoConfigurationEntry
方法,这个方法内部又会调用getCandidateConfigurations
方法,最终调用了SpringFactoriesLoader.loadFactoryNames
方法,这个方法会去加载spring-boot-autoconfigure-2.6.2.jar
包下META-INF
目录下的spring.factories
的配置文件,把key为EnableAutoConfiguration的值列表加载进内存,封装成一个字符串集合,再把集合转成一个字符串数组
- 该注解导入一个
2、一个方法 SpringApplication.run(引导类.class, args);
底层就是
(new SpringApplication(primarySources)).run(args)
-
构造器【赋值操作】
- new SpringApplication(primarySources)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.addConversionService = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = Collections.emptySet(); this.isCustomEnvironment = false; this.lazyInitialization = false; this.applicationContextFactory = ApplicationContextFactory.DEFAULT; this.applicationStartup = ApplicationStartup.DEFAULT; this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); //判断有没有Servlet环境 this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); //把 spring.factories 文件中key为ApplicationContextInitializer的内容加载进内存 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); //把 spring.factories 文件中key为ApplicationListener的内容加载进内存 this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); //判断引导类是否有一个main方法 this.mainApplicationClass = this.deduceMainApplicationClass(); }
-
run方法
public ConfigurableApplicationContext run(String... args) { long startTime = System.nanoTime(); DefaultBootstrapContext bootstrapContext = this.createBootstrapContext(); ConfigurableApplicationContext context = null; this.configureHeadlessProperty(); //封装之前构造器加载进内存监听器为SpringApplicationRunListeners SpringApplicationRunListeners listeners = this.getRunListeners(args); //开启监听器 listeners.starting(bootstrapContext, this.mainApplicationClass); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //预处理环境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments); this.configureIgnoreBeanInfo(environment); //打印Logo Banner printedBanner = this.printBanner(environment); //创建容器 context = this.createApplicationContext(); context.setApplicationStartup(this.applicationStartup); //预解析spring容器 this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); //初始化spring容器 this.refreshContext(context); this.afterRefresh(context, applicationArguments); //统计启动时间 Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup); } //开启监听器 listeners.started(context, timeTakenToStartup); //回调接口,应用运行器,命令行运行器 this.callRunners(context, applicationArguments); } catch (Throwable var12) { this.handleRunFailure(context, var12, listeners); throw new IllegalStateException(var12); } try { Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); listeners.ready(context, timeTakenToReady); return context; } catch (Throwable var11) { this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null); throw new IllegalStateException(var11); } }
run方法会去读取@EnableAutoConfigurationl加载进内存的字符串数组,通过上下文环境判断是否导入起步依赖,是否应用了各种Conditional注解,创建满足条件的bean并注入到Spring容器中