SpringBoot原理(一)--启动流程

SpringBoot启动流程

以下将从springboot的入口类SpringApplication.run(TestApplication.class,args);开始分析

1 进入run方法会先调用new SpringApplication()构造方法进行初始化操作

	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//把primpriarySources(就是传过来的启动类)放入一个set
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//判断当前web类型(REACTIVE,NONE,SERVLET),这里返回SERVLET
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		/**
		从两个spring.factories(分别是springboot和springboot-autoconfigure包里的
		META-INF/spring.factories,jar包都是放入classpath目录中的,
		classpath下有多少个spring.factories就读取多少个)中取出7个初始化器
		(根据ApplicationContextInitializer作为key来取),
		取出的只是类得完全限定名,然后进行实例化放到initializers中(是一个list)
		*/
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		/**
		从两个spring.factories中取出11个监听器器,取出的只是类得完全限定名,
		然后进行实例化放到listeners中(是一个list)
		*/
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}

1.1 上一步中的getSpringFactoriesInstances方法

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		
		//这个方法执行的核心方法是SpringFactoriesLoader.loadFactoryNames
		//其实就是解析spring.factories,从中取出类得完全限定名,放入一个set中
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		//根据得到的类的完全限定名,通过反射机制实例化,放入list
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

2 执行run方法

	public ConfigurableApplicationContext run(String... args) {
	    //创建计时器对象StopWatch
		StopWatch stopWatch = new StopWatch();
		//开始计时
		stopWatch.start();
		//设置handless的属性并设置到系统属性中
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		//从spring.factories获取一个监听器(EventPublishingRunListener)
		SpringApplicationRunListeners listeners = getRunListeners(args);
		/**
		  发布一个事件,若new SpringApplication()构造方法中加载的监听器对这个事件有监听,
		   就执行相应逻辑(观察者模式)
		*/
		listeners.starting();
		try {
		//设置换命令行参数
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			//准备环境对象,创建环境对象;加载系统参数;设置环境监听器集合
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			//忽略一些bean的信息
			configureIgnoreBeanInfo(environment);
			//打印banner图
			Banner printedBanner = printBanner(environment);
			//创建应用程序上下文
			context = createApplicationContext();
			//准备异常报告期
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			/**
				准备上下文环境(向上下文环境设置一些属性值)
                 --设置环境对象
                 --进行初始化操作
                 --发布一个监听事件,若listeners里的监听器对该事件有监听,则执行相应操作
                 --获取beanFactory工厂(DefaultListableBeanFactory),注册一些单例对象
                  --load()对应的资源(加载启动类,自动装配会用到)
			*/
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            /**
              调用过程和spring的refresh()一样,这里不再说明,
              若不了解,请阅读本人上一篇文章ioc原理
              自动装配在refresh()中的invokeBeanFactoryPostProcessors()方法中实现
              tomcat在refresh()中的onRefresh()方法中的createWebServer()实现
              关于自动装配请看本人下一篇文章
            */
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

//未完待续,自动装配请看本人下一篇文章

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBoot的运行原理启动流程可以通过分析SpringApplication类的main方法来理解。在Spring Boot应用中,通常会有一个类作为启动类,该类上标注了@SpringBootApplication注解。在这个类的main方法中,调用了SpringApplication类的run方法来启动应用。 引用中的代码展示了一个简单的SpringApplication类的示例。在main方法中,通过调用SpringApplication.run方法来运行Spring Boot应用。其中,第一个参数是启动类的Class对象,第二个参数是命令行参数。这个方法会执行一系列的步骤来初始化并启动应用。 引用中提到了一个注意事项,即Spring Boot启动类最好放在root package下,因为默认不指定basePackages。这是因为Spring Boot会基于启动类所在的包及其子包进行扫描和自动配置。 引用中提供了更详细的启动过程和相关流程的概览。其中涉及到的关键点包括: - 使用@Configuration注解标注的类,用于声明配置信息 - 使用@ComponentScan注解进行组件扫描,扫描指定包及其子包,将被@Component、@Service、@Repository、@Controller等注解标注的类识别为Spring Bean - 使用@EnableAutoConfiguration注解进行自动配置,根据类路径下的META-INF/spring.factories文件中的配置进行自动装配 - AutoConfigurationPackage注解用于导入AutoConfigurationImportSelector类,该类负责自动配置的加载和注册 - Spring FactoriesLoader用于加载spring.factories文件中的配置信息 - 启动流程的概览图展示了整个启动过程的大致流程 总的来说,SpringBoot的运行原理启动流程包括了对配置的解析、组件的扫描、自动配置的加载和注册等步骤。通过这些步骤,Spring Boot能够快速地进行应用的启动和初始化。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot启动流程及其原理](https://blog.csdn.net/qq_45824905/article/details/117202065)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SPRINGBOOT启动流程及其原理](https://blog.csdn.net/wender/article/details/121228653)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值