springboot启动过程学习记录

SpringBoot启动过程学习记录

	//主程序入口
	public static void main(String[] args) {
        SpringApplication.run(FirstSpringBootApplication.class, args);
    }

	//SpringBoot框架静态run方法
	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}
	
	//重载的run方法
	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

SpringBoot项目,启动的方式,默认是使用 SpringApplication.run(Class<?> primarySource, String… args) 方法来启动的,然后run方法呢,分为两部分,一部分是构建SpringApplication对象的过程,还有一部分是run

1.构建过程

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

程序入口,首先把主程序的class,和运行参数args作为参数传到run方法

	public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

debug断点调试

程序进来后可以看到,我们传的FirstSpringBootApplication.class,args
然后他把我们的字节码对象封装成了一个数组对象,然后继续运行了另外一个run方法

	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

这是一个重载的run方法,在这里,就能看到我们的2部分了,一部分是new SpringApplication(primarySources)
一部分是run(args)
debug断点调试
我们继续往下看new SpringApplication(primarySources)

	public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}

这是一个构造方法,调用了另一个构造方法,继续往下看另一个构造方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader; //赋值给resourceLoader 前面传的是一个null值
		Assert.notNull(primarySources, "PrimarySources must not be null"); //断言,判断primarySources
		//使用primarySources创建了一个set集合赋值给primarySources 
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); 
		/**
		*这一步,主要是判断SpringBoot是什么程序
		*WebApplicationType是一个枚举类,deduceFromClasspath()方法,主要通过各种全限定类名,判断各种类的可加载情况
		*这里就不做过多的分析了
		*/
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		/**
		*getSpringFactoriesInstances方法,是通过传递的字节码对象,获取类加载器,
		*通过使用给定的类加载器从"META-INF/spring.factories"加载给定类型的工厂实现的完全限定类名。
		*通过全限定类名,创建工厂实现的实例集合。
		*/
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

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) {
		//getClassLoader()方法获取传进来的字节码对象的类加载器,如果传的是null则获取默认的类加载器
		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;
	}

请注意,**getClassLoader()**方法

	public ClassLoader getClassLoader() {
		//判断this.resourceLoader,这个属性,在上面this(null, primarySources);调用这个构造方法的时候,传了一个null参数
		//public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		//this.resourceLoader = resourceLoader; //赋值给resourceLoader 前面传的是一个null值
		//所以,这里这个if是为false,所以我们获取到的是getDefaultClassLoader
		//
		if (this.resourceLoader != null) {
			return this.resourceLoader.getClassLoader();
		}
		/**
		*返回要使用的默认 ClassLoader:通常是线程上下文 ClassLoader; 加载 ClassUtils 类的 ClassLoader 将用作后备。
		*/
		return ClassUtils.getDefaultClassLoader();
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值