Spring boot源码提纲

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

一. new SpringApplication()

  1. SpringApplication.run(primarySource.class, args); 启动spring程序

  2. 推断项目类型(REACTIVE,NONE,SERVLET)根据当前项目引入的spring jar包 SpringApplication.deduceWebApplicationType()。

maven引入spring-boot-starter依赖的话,deduceWebApplicationType=NONE

maven引入spring-boot-starter-web依赖的话, deduceWebApplicationType=SERVLET

  1. 搜索当前项目下所有的 “META-INF/spring.factories”文件里的ApplicationContextInitializer的实现类使用SpringFactoriesLoader.loadFactoryNames(type, classLoader)加载并实例化,并存放在SpringApplication.initializers中。

ApplicationContextInitializer的作用:Callback interface for initializing a Spring ConfigurableApplicationContext prior to being refreshed。

  1. 搜索当前项目下所有的 “META-INF/spring.factories”文件里的ApplicationListener的实现类使用SpringFactoriesLoader.loadFactoryNames(type, classLoader)加载并实例化,并存放在SpringApplication.listeners中。

ApplicationListener的作用:监听SpringApplication,Environment事件源的各种事件。

5.根据调用堆栈找到main方法所在的类,并存放在SpringApplication.mainApplicationClass。

StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();

for (StackTraceElement stackTraceElement : stackTrace) {

if (“main”.equals(stackTraceElement.getMethodName())) {

return Class.forName(stackTraceElement.getClassName());

}

}

primarySources vs mainApplicationClass, primarySources是SpringApplication.run的参数,mainApplicationClass是main方法所在的类。

二. springApplication.run()

  1. 搜索当前项目下所有的 “META-INF/spring.factories”文件里的SpringApplicationRunListener的实现类加载并实例化,目前默认系统只提供一个实现类EventPublishingRunListener。

  2. 广播ApplicationStartingEvent事件,事件源为springApplication,给所有的SpringApplication.listeners监听者。

LoggingApplicationListener(挑选一个可用的日志系统)/BackgroundPreinitializer(启动后台线程)/DelegatingApplicationListener(去delegate other listeners,是给用户作扩展使用:可以在property里定义key为context.listener.classes的listener)/LiquibaseServiceLocatorApplicationListener四个监听可以处理此事件。

举例:

当某个事件源(如:SpringApplication, ConfigurableApplicationContext,ConfigurableEnvironment)执行某个操作(或事件,如:ApplicationStartingEvent,ApplicationReadyEvent, ApplicationEnvironmentPreparedEvent)后,SpringApplicationRunListeners.listeners会遍历所有的listener(发布器)(如:EventPublishingRunListener),这个listener发布器在由事件源初始化时已经绑定了事件源,发布器通过SimpleApplicationEventMulticaster将事件广播给所有的SpringApplication.listeners[i].onApplicationEvent()(如:LoggingApplicationListener,DelegatingApplicationListener),SpringApplication.listeners[i].onApplicationEvent()在一个方法里根据不同事件类型(ApplicationStartingEvent,ApplicationReadyEvent, ApplicationEnvironmentPreparedEvent)做不同的操作。

模式:

1)角色:事件源,发布器,监听器,事件。

2)流程:由事件源来创建发布器,创建完成后发布器就有了事件源的引用,由事件源调用发布器执行某事件,发布器先创建Event,Event的属性source使用创建发布器的事件源,然后会遍历所有注册了接受事件源(listener.supportsSourceType)的当前操作(listener.supportsEventType)的监听器去执行onAction.

3)关系:事件源依赖发布器,发布器反过来关联事件源,发布器依赖事件和监听器,监听器依赖事件。通过发布器和事件,将事件源和监听器解耦。对于可响应式组件:如HTML里的组件,事件源和发布器是同一角色,因为Button能自己感应事件并发布事件,这样就只有事件源,事件,事件处理函数三个角色。

  1. 创建Environment对象,如果项目类型为SERVLET,则创建StandardServletEnvironment容器,否则创建StandardEnvironment。

广播ApplicationEnvironmentPreparedEvent事件, ConfigFileApplicationListener/AnsiOutputApplicationListener/LoggingApplicationListener/ClasspathLoggingApplicationListener/BackgroundPreinitializer/FileEncodingApplicationListener六个监听可以处理此事件,其中ConfigFileApplicationListener会搜索当前项目下所有的 “META-INF/spring.factories”文件里的EnvironmentPostProcessor的实现类加载并实例化, 并立即执行这些PostProcessor(SystemEnvironmentPropertySourceEnvironmentPostProcessor,SpringApplicationJsonEnvironmentPostProcessor,CloudFoundryVcapEnvironmentPostProcessor,ConfigFileApplicationListener)。其中ConfigFileApplicationListener这个PostProcessor会搜索当前项目下所有的 “META-INF/spring.factories”文件里的PropertySourceLoader的实现类加载并实例化,并立即执行这些PropertySourceLoader(PropertiesPropertySourceLoader,YamlPropertySourceLoader)去load加载配置文件。

最后environment生成数据对象格式如下:

commandLineArgs:[] 命令行参数 main方法的args参数

servletContextInitParams:[] servletcontext初始化参数

systemProperties:[java.io.tmpdir:/tmp,sun.jnu.encoding:utf8…] jvm参数 System.getProperties()

systemEnvironment:[PWD:/home/lewis,username:lewis…] 系统变量参数 System.getenv()

applicationConfig(classpath:/application.properties):[key:value…] application.properties配置参数

Environment实例有一属性是PropertySources,PropertySources也有一属性是List,environment.getProperty(key)会遍历所有的PropertySource来查找key的value。

参考配置:

https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/pdf/spring-boot-reference.pdf参考文档中的Appendix A. Common application properties部分提供了sample配置。

如何使用application.properties文件来初始化子模块:

以logging为例,LoggingApplicationListener能够接受ApplicationEnvironmentPreparedEvent事件来初始化日志子系统。当env加载完配置信息后会发布ApplicationEnvironmentPreparedEvent事件,监听便会拿到相应的当前子模块所需的配置信息”logging.config”前辍来初始化日志模块。

手动找配置文件和对应的Properties类:

下载spring-boot源码,进入到spring-boot-project目录执行shell命令:find ./ -path “*src/main*” -name “*.java” |xargs grep -e “@ConfigurationProperties(\|@ConditionalOnProperty(” | sed -r ‘s/.*\///g’

profile:根据不同的变量值(spring.profiles.active=[dev|test|prod])使用不同的配置文件。spring.profiles.active=dev可以通过application.properties或java参数或jvm参数或系统环境参数传入,根据这个值来决定使用application-dev.properties这个配置文件。也可以定义不同环境的Propreties配置类,并在该类上使用@Profile(value = “prod|test|dev”)注解。

  1. new ConfigurableApplicationContext(), 根据推断项目类型(REACTIVE,NONE,SERVLET)来创建相应的对象,

SERVLET:AnnotationConfigServletWebServerApplicationContext

NONE:AnnotationConfigApplicationContext

REACTIVE:AnnotationConfigReactiveWebServerApplicationContext

这些ApplicationContext有四个重要成员变量:

DefaultListableBeanFactory beanFactory;

ConfigurableEnvironment environment;

AnnotatedBeanDefinitionReader reader;

ClassPathBeanDefinitionScanner scanner;

在初始化reader时会调用AnnotationConfigUtils.registerAnnotationConfigProcessors(applicationContext); 该方法会硬编码注册以下PostProcessor的BeanDefinition到容器: context{reader:AnnotatedBeanDefinitionReader{

AnnotationConfigUtils.registerAnnotationConfigProcessors(context);

context.beanDefinitionMap = {

internalConfigurationAnnotationProcessor:ConfigurationClassPostProcessor

internalAutowiredAnnotationProcessor:AutowiredAnnotationBeanPostProcessor

internalRequiredAnnotationProcessor:RequiredAnnotationBeanPostProcessor

internalCommonAnnotationProcessor:CommonAnnotationBeanPostProcessor

internalEventListenerProcessor:EventListenerMethodProcessor

internalEventListenerFactory:DefaultEventListenerFactory

}

},

scanner:ClassPathBeanDefinitionScanner}

  1. applyInitializers(context); DelegatingApplicationContextInitializer/ContextIdApplicationContextInitializer/ConfigurationWarningsApplicationContextInitializer/ServerPortInfoApplicationContextInitializer/SharedMetadataReaderFactoryContextInitializer/ConditionEvaluationReportLoggingListener

DelegatingApplicationContextInitializer是给用户作扩展使用:可以在property里定义key为context.initializer.classes的initializer。

执行所有的SpringApplication.initializers.stream(init->init.initialize(context)); 其中ConfigurationWarningsApplicationContextInitializer会添加ConfigurationWarningsPostProcessor到applicationContext.beanFactoryPostProcessors,SharedMetadataReaderFactoryContextInitializer会添加CachingMetadataReaderFactoryPostProcessor到applicationContext.beanFactoryPostProcessors。

ContextIdApplicationContextInitializer:

往DefaultListableBeanFactory extend DefaultSingletonBeanRegistry里注册bean:

beanFactory.singletonObjects.put(“ContextIdApplicationContextInitializer$ContextId”, new ContextIdApplicationContextInitializer$ContextId);

beanFactory.registeredSingletons.add(“ContextIdApplicationContextInitializer$ContextId”);

ConfigurationWarningsApplicationContextInitializer:

context.addBeanFactoryPostProcessor(new ConfigurationWarningsPostProcessor(getChecks()));

SharedMetadataReaderFactoryContextInitializer:

applicationContext.addBeanFactoryPostProcessor(new CachingMetadataReaderFactoryPostProcessor());

ConditionEvaluationReportLoggingListener:

applicationContext.addApplicationListener(new ConditionEvaluationReportListener());

context.getBeanFactory().registerSingleton(“springApplicationArguments”,applicationArguments);

  1. load primarySources:

6.1创建BeanDefinitionLoader根据context和primarySources,并会创建AnnotatedBeanDefinitionReader的annotatedReader成员变量和XmlBeanDefinitionReader的xmlReader成员变量,以及ClassPathBeanDefinitionScanner的scanner的成员变量。

BeanDefinitionLoader{annotatedReader:AnnotatedBeanDefinitionReader,xmlReader:XmlBeanDefinitionReader,scanner:ClassPathBeanDefinitionScanner,scanner.addExcludeFilter:ClassExcludeFilter}

6.2通过annotatedReader.register(primarySources)注册BeanDefinition。

创建AnnotatedGenericBeanDefinition abd, AnnotatedGenericBeanDefinition{metadata:StandardAnnotationMetadata{annotations:List}, scope:[singleton|prototype]}

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd),将通用的注解@Lazy,@Primary,@DependsOn,@Role,@Description的value信息设置到abd的相应成员变量上。

BeanDefinitionReaderUtils.registerBeanDefinition(primarySoruce,register) 注册primarySoruce的BeanDefinition到register。

  1. 广播ApplicationPreparedEvent事件。ConfigFileApplicationListener/LoggingApplicationListener/BackgroundPreinitializer/DelegatingApplicationListener

其中ConfigFileApplicationListener的onApplicationPreparedEvent方法中会添加PropertySourceOrderingPostProcessor到applicationContext.beanFactoryPostProcessors。

context.addBeanFactoryPostProcessor(new PropertySourceOrderingPostProcessor(context));

  1. applicationContext.refrsh():

8.1设置ConfigurableListableBeanFactory的初始属性:

beanFactory.addBeanPostProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector)

ConfigurableListableBeanFactory.singletonObjects里注册实例有:[autoConfigurationReport, org.springframework.boot.context.ContextIdApplicationContextInitializer$ContextId, springApplicationArguments, springBootBanner, springBootLoggingSystem, environment, systemProperties, systemEnvironment]。

8.2 applicationContext.invokeBeanFactoryPostProcessors([ConfigurationWarningsPostProcessor,CachingMetadataReaderFactoryPostProcessor,PropertySourceOrderingPostProcessor,ConfigurationClassPostProcessor])

这里的BeanFactoryPostProcessors分为两种:BeanDefinitionRegistryPostProcessor和普通的BeanFactoryPostProcessor。

最关键的是执行ConfigurationClassPostProcessor这个BeanFactoryPostProcessor,它的processConfigBeanDefinitions方法会遍历ConfigurableListableBeanFactory中已经注册的BeanDefinition,找出所有@Configuration的类。

PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(internalConfigurationAnnotationProcessor, context);

搜索已注册的BeanDefinition中含有Configuration注解的Beans[只有primarySoruces],然后ConfigurationClassParser去解析

ConfigurationClassParser.doProcessConfigurationClass()递归调用// Parse each @Configuration class

parser.processMemberClasses(configClass, sourceClass);// Recursively process any member (nested) classes first

parser.processPropertySource(propertySource);//Process any @PropertySource annotations

ComponentScanAnnotationParser.parse()// Process any @ComponentScan annotations

定义ClassPathBeanDefinitionScanner,如果@ComponentScan没有定义basePackage,它从primarySoruces的package位置开始,搜索所有的Component

parser.processImports()// Process any @Import annotations

ConfigurationClass.addImportedResource(resolvedResource, readerClass)// Process any @ImportResource annotations

ConfigurationClass.addBeanMethod()// Process individual @Bean methods

parser.processDeferredImportSelectors();//加载所有的autoconfig class,并且只加载autoconfig里没有Condition注解的类。

AutoConfigurationImportSelector.selectImports()//搜索所有spring.factories中的EnableAutoConfiguration。并通过primarySoruces中的

//@EnableAutoConfiguration中的attribute进行过滤。

parser.processImports(); //将所有的autoconfig class中有Import注解的类进行加载。

ConditionEvaluator.shouldSkip()//会作Condition条件过滤。

internalConfigurationAnnotationProcessor.reader.loadBeanDefinitions(configClasses); //将解析得到的parser.configClasses的所有BeanDefinition注册到容器。

loadBeanDefinitionsForBeanMethod(beanMethod);//注册@Bean注解的method到BeanDefinition容器。

目前只有primarySoruces的类,ConfigurationClassParser.doProcessConfigurationClass(primarySoruces), 该方法会解析该config类的@PropertySource,@ComponentScan,@Import,@ImportResource,@Bean注解,该方法doProcessConfigurationClass会被递归调用,解析满足条件的所有注解类。

@ComponentScan注解会ComponentScanAnnotationParser.parse(){ClassPathBeanDefinitionScanner.doScan()},并将所有的@Component注册成为BeanDefinition。

将所有@Component的类注册BeanDefinition到容器里。它使用ClassPathScanningCandidateComponentProvider判断是否满足规则:

ClassPathScanningCandidateComponentProvider{

private final List includeFilters = new LinkedList<>();

private final List excludeFilters = new LinkedList<>();

}

TypeFilter是一系列的策略实现类,用来

AutoConfigurationExcludeFilter.isConfiguration(MetadataReader metadataReader) {

return metadataReader.getAnnotationMetadata()

.isAnnotated(Configuration.class.getName());

}

AnnotationTypeFilter{

Class<? extends Annotation> annotationType; 这个在ClassPathScanningCandidateComponentProvider.registerDefaultFilters方法中会赋值(org.springframework.stereotype.Component.class)

protected boolean matchSelf(MetadataReader metadataReader) {

AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();

return metadata.hasAnnotation(this.annotationType.getName()) ||

(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));

}

}

其中ConfigurationClassPostProcessor.postProcessBeanFactory会将所有的@Configuration注解的类enchance成cglib代理的类,这些config类不仅是用户定义的,包括spring框架里的config类,只是将类加载enhance,并没有实例化。

class ConfigurationClassEnhancer {

// The callbacks to use. Note that these callbacks must be stateless.

private static final Callback[] CALLBACKS = new Callback[] {

new BeanMethodInterceptor(),

new BeanFactoryAwareMethodInterceptor(),

NoOp.INSTANCE

};

}

@Import注解会将value的类注册成为BeanDefinition。

ConfigurationClassParser.processDeferredImportSelectors()

AutoConfigurationImportSelector.selectImports()这个方法会调用AutoConfigurationImportSelector.getCandidateConfigurations会搜索当前项目下所有的 “META-INF/spring.factories”文件里的EnableAutoConfiguration的实现类。

解析所有这些@EnableAutoConfiguration的类,看是否在当前项目下引用,如果该类存在就将其注册成为BeanDefinition。

8.3 applicationContext.registerBeanPostProcessors() //Register BeanPostProcessor that intercept bean creation.

8.4 context.finishBeanFactoryInitialization();// Instantiate all remaining (non-lazy-init) singletons.

beanFactory.preInstantiateSingletons()

beanFactory.getBean(beanFactory.beanDefinitionNames[i]); //创建实例,并添加到factory.singletonObjects中。

工具方法:

AnnotationUtils.findAnnotation(clazz, Component.class)//判断clazz上有没有@Component的注解。

XML配置:

1) 将隐式地向 Spring 容器注册AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及equiredAnnotationBeanPostProcessor 这 4 个 BeanPostProcessor。

2)提供了自动扫描注解类并将其注册到容器,它还包含了autowire自动装配功能。


来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring boot源码提纲

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏