springboot启动 源码

public ConfigurableApplicationContext run(String... args) {

StopWatch stopWatch = new StopWatch();

stopWatch.start();

ConfigurableApplicationContext context = null;

FailureAnalyzers analyzers = null;

configureHeadlessProperty();

SpringApplicationRunListeners listeners = getRunListeners(args);

listeners.started();

try {

ApplicationArguments applicationArguments = new DefaultApplicationArguments(

args);

ConfigurableEnvironment environment = prepareEnvironment(listeners,

applicationArguments);

Banner printedBanner = printBanner(environment);

context = createApplicationContext();//逻辑是,判断是不是web环境,决定生成哪一种context,AnnotationConfigEmbeddedWebApplicationContext,

还是AnnotationConfigApplicationContext

analyzers = new FailureAnalyzers(context);

prepareContext(context, environment, listeners, applicationArguments,

printedBanner);//最关键的一个方法load()是把启动类给注册到工厂里

refreshContext(context);//在AnnotationConfigEmbeddedWebApplicationContext的构造函数中,new AnnotatedBeanDefinitionReader(this),而这个构造方法中

会向工厂注册(注意注册和实例化不同)ConfigurationClassPostProcessor(其他PostProcessor先不说),在本方法中,refresh工厂的时候,在invokeBeanFactoryPostProcessors这一步,

会调用所有实现BeanFactoryPostProcessor接口和BeanDefinitionRegistryPostProcessor接口的类的两个相应方法,

@Configuration注解的解析:

上面的两个方法都最终会执行processConfigBeanDefinitions方法,逻辑是判断所有已经注册的beanname,上面有没有注解@Configuration,如果有的话,用ConfigurationClassParser解析

parser = new ConfigurationClassParser,parser.parse(candidates);

解析的逻辑是:

对所有的内部类,重新进行parse方法(不严谨但是差不多啦)

然后看看自己的类上面有没有

@PropertySource注解,

@ComponentScan注解:逻辑是:有该注解的类,扫描下面的包,得到一批beanDefinition,然后这批bd出来之后直接用ConfigurationClassUtils.checkConfigurationClassCandidate方法判断,然后进入processConfigurationClass

方法,但是如果被扫描包里面,只有@Import注解的类,是不会扫描其中的@Import,@Bean等注解的,那说明得到这批beanDefinition的时候,已经过滤了,只扫描有@Component注解的(@Configuration也是包含@Component的)。

具体办法是:componentScanParser.parse方法中,scanner.doScan方法中findCandidateComponents中isCandidateComponent的excludeFilters和includeFilters,而默认的filter只会包含@Component或者其他的什么

@ManagedBean、JSR-330:@Named等等。上面说的scanner是ClassPathBeanDefinitionScanner,在构造方法中有registerDefaultFilters();

其实这样看起来,@[email protected]注解没啥用,完全可以用@component代替///@EnableAutoConfiguration其实是两个@Import注解的组合,一个导入AutoConfigurationImportSelector.class,一个通过

@AutoConfigurationPackage导入AutoConfigurationPackages.Registrar.class

@Import注解:先根据@Import注解里面的值,看该类上面有没有@Import注解,如果有,也加入进来,然后对于所有的候选类,如果是ImportSelector,或者ImportBeanDefinitionRegistrar,如果都不是,那么当作@Configuration

@ImportResource注解,

@Bean注解,

然后看它的父类,parse父类(也不严谨但是也差不多啦),直到父类以java开头?

所以这里可以看出,对类上面有没有@Configuration的判断,只在当前类上进行,而它的内部类和父类,都不做判断。那么一个@Configuration的类,它的内部类和父类,都要判断里面的注解类型

最后,会放到 工厂的 configurationClasses属性中

afterRefresh(context, applicationArguments);

listeners.finished(context, null);

stopWatch.stop();

if (this.logStartupInfo) {

new StartupInfoLogger(this.mainApplicationClass)

.logStarted(getApplicationLog(), stopWatch);

}

return context;

}

catch (Throwable ex) {

handleRunFailure(context, listeners, analyzers, ex);

throw new IllegalStateException(ex);

}

}

原文地址:https://www.cnblogs.com/chuliang/p/9081420.html

时间: 2024-10-21 00:59:52

springboot启动 源码的相关文章

Springboot启动源码详解

我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } 从上面代码可以看出,Annotation定义(@SpringBootApplication)和类定义(SpringApplication.run)最

SpringBoot启动源码探究---listeners.starting()

1.首先调用starting()方法,其内部是一个对所有listener的starting()调用的for循环,然后每个listener调用另一个starting方法,其内部调用multicastEvent方法,其又调用其他multicastEvent方法,其又继续调用其他的multicastEvent方法,然后在里面进行了这样的逻辑:先根据事件类型获取到合适的监听器,然后对这些合适的监听器遍历,每一个监听器都开启一个独立的线程去执行监听(具体放在下一节) 2.其中获取到合适的监听器很重要,如何

springboot启动源码解析

/** *SpringApplication */ //构造器初始化 public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { this.sources = new LinkedHashSet(); //横幅模式 OFF,CONSOLE,LOG; this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addComm

SpringBoot启动源码探究---getRunListener()

该方法目的是获取SpringApplicationRunListener getRunListener()-----调用----> getSpringFactoriesInstances()----调用-----> SpringFactoriesLoader.loadFactoryNames()-----调用----> getResources("spring.factories") 和 getProperty("SpringApplicationRunLi

Jfinal启动源码解读

本文对Jfinal的启动源码做解释说明. PS:Jfinal启动容器可基于Tomcat/Jetty等web容器启动,本文基于Jetty的启动方式做启动源码的解读和分析,tomcat类似. 入口  JFinalConfig的继承类的Main方法为入口,实例代码继承类为:DemoConfig,Main方法如下: public static void main(String[] args) { /** * 特别注意:Eclipse 之下建议的启动方式 */ JFinal.start("WebRoot&

Android之rild进程启动源码分析

Android 电话系统框架介绍 在android系统中rild运行在AP上,AP上的应用通过rild发送AT指令给BP,BP接收到信息后又通过rild传送给AP.AP与BP之间有两种通信方式: 1.Solicited Response:Ap向Bp发送请求,Bp给Ap发送回复,该类型的AT指令及其回调函数以数组的形式存放在Ril_commands.h文件中: {数组中的索引号,请求回调函数,响应回调函数} [plain] view plaincopy {0, NULL, NULL},      

Openstack学习笔记之——Neutron-server服务加载与启动源码分析(三)

本文是在学习Openstack的过程中整理和总结,由于时间和个人能力有限,错误之处在所难免,欢迎指正! 在Neutron-server服务加载与启动源码分析(二)中搞定模块功能的扩展和加载,我们就回到Neutron-server服务加载与启动源码分析(一)中的_run_wsgi函数 <span style="font-size:14px;">def _run_wsgi(app_name): app = config.load_paste_app(app_name) ifno

Spring Boot 启动源码解析系列六:执行启动方法一

1234567891011121314151617181920212223242526272829303132333435363738394041424344 public ConfigurableApplicationContext (String... args) { StopWatch stopWatch = new StopWatch(); // 开始执行,记录开始时间 stopWatch.start(); ConfigurableApplicationContext context =

Django如何启动源码分析

Django如何启动源码分析 启动 我们启动Django是通过python manage.py runsever的命令 解决 这句话就是执行manage.py文件,并在命令行发送一个runsever字符串 解析manage.py #!/usr/bin/env python import os import sys if __name__ == "__main__": #os.environ.setdefault 方法可以修改系统环境变量,但是只能os.environ 只能影响到当前运行