SpringBoot源码分析篇一
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
</parent>
SpringApplication认知
基本介绍
此类可以用来引导和发起一个源于Java main()方法的Spring应用。默认执行以下步骤引导应用:
1、 创建适当的 ApplicationContext 实例(依赖于classpath)
2、 注册 CommandLinePropertySource 来暴露命令行参数作为Spring属性
3、 刷新应用上下文,加载所有单例Bean
4、 触发所有 CommandLineRunner Bean
属性介绍
// "banner.txt" 默认banner位置
public static final String BANNER_LOCATION_PROPERTY_VALUE = SpringApplicationBannerPrinter.DEFAULT_BANNER_LOCATION;
// "spring.banner.location" banner属性key
public static final String BANNER_LOCATION_PROPERTY = SpringApplicationBannerPrinter.BANNER_LOCATION_PROPERTY;
// 无关紧要,不用关注
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
// logging 日志
private static final Log logger = LogFactory.getLog(SpringApplication.class);
// shutdown 钩子
// 用来作为Spring Boot应用shutdown的钩子执行优雅的shutdown的执行器。此钩子追踪已注册的应用上下文以及通过 SpringApplication.getShutdownHandlers() 注册的任何操作。
static final SpringApplicationShutdownHook shutdownHook = new SpringApplicationShutdownHook();
// 主要源
private Set<Class<?>> primarySources;
// 来源
private Set<String> sources = new LinkedHashSet<>();
// 主应用类
private Class<?> mainApplicationClass;
// banner输出位置,默认控制台
private Banner.Mode bannerMode = Banner.Mode.CONSOLE;
// 日志启动信息
private boolean logStartupInfo = true;
// 添加命令行属性
private boolean addCommandLineProperties = true;
// 添加转换Service
private boolean addConversionService = true;
// banner
private Banner banner;
// 资源加载器
private ResourceLoader resourceLoader;
// Bean 名生成器
private BeanNameGenerator beanNameGenerator;
// 配置环境
private ConfigurableEnvironment environment;
// web 应用类型,none、servlet[通常是这个]、reactive
private WebApplicationType webApplicationType;
// 无头 不关注
private boolean headless = true;
// 注册 shutdown 钩子
private boolean registerShutdownHook = true;
// 应用上下文初始化器
private List<ApplicationContextInitializer<?>> initializers;
// 应用监听器
private List<ApplicationListener<?>> listeners;
// 默认属性
private Map<String, Object> defaultProperties;
// 引导注册初始化器
private List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;
// 应用属性
private Set<String> additionalProfiles = Collections.emptySet();
// 允许bean定义覆盖
private boolean allowBeanDefinitionOverriding;
// 允许循环引用
private boolean allowCircularReferences;
// 自定义环境
private boolean isCustomEnvironment = false;
// 懒初始化
private boolean lazyInitialization = false;
// 环境前缀
private String environmentPrefix;
// 应用上下文工厂
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
// 应用启动器
private ApplicationStartup applicationStartup = ApplicationStartup.DEFAULT;
构造方法分析
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 来源加载器,这里为null
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 主要来源[当前启动类]
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 从类路径推断应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
item1 推断应用类型分析
static WebApplicationType deduceFromClasspath() {
// ClassUtils.isPresent 确定类是否可被加载
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
// private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext" };
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
item2 获取Spring工厂实例【非常重要】
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}