SpringBoot 2.3.x 启动方法源码解析

本文深入探讨了SpringBoot 2.3.x的启动过程,从run方法开始,逐步解析getRunListeners、prepareEnvironment、prepareContext、refreshContext和callRunners等关键步骤,涉及环境配置、监听器、ApplicationContext初始化和Bean加载等内容。
摘要由CSDN通过智能技术生成

这是最常见的也是使用最多的SpringBoot应用程序启动类,整个SpringBoot应用启动都要靠执行run方法来启动

@SpringBootApplication
public class Hibernate52Application  {
   

	public static void main(String[] args) {
   
		SpringApplication.run(Hibernate52Application.class, args);
	}

}

点进去看看

// 这是SpringApplication的run方法
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
   
		return run(new Class<?>[] {
    primarySource }, args);
}
// 上面的run方法实际是调用这个run方法
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
   
		return new SpringApplication(primarySources).run(args);
}

首先实例化SpringApplication

private ResourceLoader resourceLoader;
private WebApplicationType webApplicationType;
private List<ApplicationContextInitializer<?>> initializers;
private List<ApplicationListener<?>> listeners;
private Class<?> mainApplicationClass;
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
		// 资源加载器
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		// JavaConfig类型的类
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// 根据classPath推导出web应用类型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// 初始化initializers属性
		setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// 设置监听器
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// 推导出主应用程序类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

SprigBootApplication 中有非常多的属性,先看这个构造方法中使用到的

  • resourceLoader 资源加载器
  • primarySources 在这就是 Hibernate52Application.class
  • webApplicationType web应用程序类型,看代码是根据Classpath推导而来
  • Initializer 元素类型为ApplicationContextInitializer的列表
  • listeners 元素类型为ApplicationListener的列表
  • mainApplicationClass 主应用程序类

上面的方法,先一个一个看

  1. deduceFormClasspath
public enum WebApplicationType {
   
/**
	 * The application should not run as a web application and should not start an
	 * embedded web server.
	 * 没有内嵌服务器
	 */
	NONE,

	/**
	 * The application should run as a servlet-based web application and should start an
	 * embedded servlet web server.
	 * Servlet类型的应用
	 */
	SERVLET,

	/**
	 * The application should run as a reactive web application and should start an
	 * embedded reactive web server.
	 * 响应式的应用 比如Spring-Webflux
	 */
	REACTIVE;

	private static final String[] SERVLET_INDICATOR_CLASSES = {
    "javax.servlet.Servlet",
			"org.springframework.web.context.ConfigurableWebApplicationContext" };

	private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";

	private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";

	private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
// 这个方法的作用就是判断当前的应用类型,通过使用反射在类路径下寻找是否存在对应的类,从而判断出该应用属于什么类型的应用
	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;
		}
}
  1. getSpringFactoriesInstances
	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
   
		return getSpringFactoriesInstances(type, new Class<?>[] {
   });
	}

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
   
		// 获取类加载器
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		// 加载指定类型在"META-INF/spring.factories"对应的类名数组
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		// 根据类名数组创建实例
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		// 排序实例
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}
	// 其中的loadFactoryNames方法并没有点进去看,其实里面的逻辑就是根据type加载在"META-INF/spring.factories"对应的类名数组
	// 在META-INF/spring.factories中,以KEY-VALUE形式存储了各个类对应的实现类们
	@SuppressWarnings("unchecked")
	private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
			ClassLoader classLoader, Object
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值