springboot源码流程解析
2021-10-30 09:59:17 33 举报
AI智能生成
springboot源码流程解析
作者其他创作
大纲/内容
1.启动流程
<span style="font-size: inherit;">SpringApplication.run(HibikiApplication.class, args);</span><br><span style="font-size: inherit;">--run(new Class<?>[] { primarySource }, args)</span><br><span style="font-size: inherit;">----new SpringApplication(primarySources).run(args)</span><br>
this(resourceLoader:null, primarySources);
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); <br>
this.webApplicationType = WebApplicationType.deduceFromClasspath(); <br>
REACTIVE
NONE
SERVLET
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); <br>
getSpringFactoriesInstances(ApplicationContextInitializer.class,new Class<?>[] {})<br>
getClassLoader()
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader))<br>>>loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList())
(List)loadSpringFactories(classLoader)
getOrDefault(factoryTypeName, Collections.emptyList()
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names)
setInitializers<br>--this.initializers = new ArrayList<>(initializers)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); <br>--this.listeners = new ArrayList<>(listeners);<br>
this.mainApplicationClass = deduceMainApplicationClass(); <br>
#run(args)
ConfigurableApplicationContext context = null
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>()
SpringApplicationRunListeners listeners = getRunListeners(args);
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,<br> getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args))
listeners.starting()
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));<br>
RestartApplicationListener#onApplicationStartingEvent<br>
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
若没有显示指定容器的类型,则根据this.webApplicationType创建class
若为SERVLET,创建AnnotationConfigServletWebServerApplicationContext,反射实例化<br>
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,<br><br> new Class[] { ConfigurableApplicationContext.class }, context);<br>
prepareContext(context, environment, listeners, applicationArguments, printedBanner);<br>
context.setEnvironment(environment)
postProcessApplicationContext(context); <br>
applyInitializers(context);
循环依次initializer.initialize(context)
listeners.contextPrepared(context);
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
若this.lazyInitialization:默认false,可在yaml配置main:lazy-initialization:true<br>context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor())<br>
Set<Object> sources = getAllSources();<br>
load(context, sources.toArray(new Object[0]))
listeners.contextLoaded(context);
refreshContext(context);<br>
refresh((ApplicationContext) context);<br>
大部分与普通springioc容器流程相同,详情见springioc流程分析
不同点
#invokeBeanFactoryPostProcessors<br>
ServletWebServerApplicationContext#Onfresh<br>
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
createWebServer()<br>
ServletWebServerFactory factory = getWebServerFactory();
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class)<br>>>return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class)
this.webServer = factory.getWebServer(getSelfInitializer());
getSelfInitializer()<br>--return this::selfInitialize: 传入方法引用,匿名函数,在之后webServer初始化时调用<br>>>>>selfInitialize(ServletContext servletContext)
prepareWebApplicationContext(servletContext);
Object rootContext = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this);
setServletContext(servletContext);
registerApplicationScope(servletContext);
ServletContextScope appScope = new ServletContextScope(servletContext);
getBeanFactory().registerScope(“application”, appScope);
servletContext.setAttribute(ServletContextScope.class.getName(), appScope);
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);<br>--registerEnvironmentBeans(bf, sc, (ServletConfig)null);<br>----bf.registerSingleton("servletContext", servletContext);<br>----bf.registerSingleton("contextParameters", Collections.unmodifiableMap(attributeMap));<br>----bf.registerSingleton("contextAttributes", Collections.unmodifiableMap(attributeMap));
for (ServletContextInitializer beans : getServletContextInitializerBeans())<br>>>beans.onStartup(servletContext);
getServletContextInitializerBeans()<br>--return new ServletContextInitializerBeans(getBeanFactory());<br>----addServletContextInitializerBeans(beanFactory);<br>----addAdaptableBeans(beanFactory);
getWebServer(ServletContextInitializer... initializers)
Tomcat tomcat = new Tomcat();
prepareContext(tomcat.getHost(), initializers);
TomcatEmbeddedContext context = new TomcatEmbeddedContext();
addDefaultServlet(context);
configureContext(context, initializersToUse);
TomcatStarter starter = new TomcatStarter(initializers);
for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {<br> customizer.customize(context);<br> }
postProcessContext(context);
return getTomcatWebServer(tomcat);<br>--return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
getBeanFactory().registerSingleton("webServerGracefulShutdown",<br><br> new WebServerGracefulShutdownLifecycle(this.webServer));<br>
getBeanFactory().registerSingleton("webServerStartStop",<br><br> new WebServerStartStopLifecycle(this, this.webServer));
GenericWebApplicationContext#initPropertySources();<br>--ConfigurableEnvironment env = this.getEnvironment();<br>--env.initPropertySources(this.servletContext, (ServletConfig)null);<br>----WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
sources.replace("servletContextInitParams", new ServletContextPropertySource("servletContextInitParams", servletContext));
sources.replace("servletConfigInitParams", new ServletConfigPropertySource("servletConfigInitParams", servletConfig));
#registerListeners
详情见springioc流程分析
#finishRefresh<br>
getLifecycleProcessor().onRefresh();
DefaultLifecycleProcessor#startBeans(true);
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
webServerStartStop#start<br>
this.webServer.start();
this.running = true;
this.applicationContext.publishEvent<br>(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
webServerGracefulShutdown<br>
根据各个bean不同的应用阶段分组
调用LifecycleGroup中的所有Lifecycle的start方法
this.running = true;
this.webServer.start()
context.registerShutdownHook();
afterRefresh(context, applicationArguments);<br>
listeners.started(context);<br>
callRunners(context, applicationArguments);
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());<br>
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
循环callRunner((CommandLineRunner) runner, args);
listeners.running(context);
2.@SpringBootApplication<br>
@SpringBootConfiguration
@Configuration
@Component
说明Spring的配置类也是Spring的一个组件
@ComponentScan(excludeFilters = {x,x})<br>
AutoConfigurationExcludeFilter
TypeExcludeFilter
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)<br>自动注册包---主配置类所在的包:com.kuang.demo包
#registerBeanDefinitions<br>
@Import(AutoConfigurationImportSelector.class)自动导入包的核心
#selectImports(AnnotationMetadata annotationMetadata)
#isEnabled(AnnotationMetadata metadata)
#getAutoConfigurationEntry(AnnotationMetadata annotationMetadata)
#getCandidateConfigurations(annotationMetadata, attributes)
导入的类:自动导入选择器AutoConfigurationImportSelector
类里有个方法:getAutoConfigurationEntry<br>作用:获得自动配置实体
该方法里调用了方法:getCandidateConfigurations<br>目的:获取候选的配置
该方法调用了<br>List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader())<br>关注参数 最后返回的就是自动配置的类:就是META-INF/factories下的自动配置类名的集合
getSpringFactoriesLoaderFactoryClass()<br><br>return EnableAutoConfiguration.class;<br><br>获取标注了EnableAutoConfiguration这个注解的类:<br>包括主启动类public class Application
应用
自定义运行监听器<br>
implements SpringApplicationRunListener<br>extends EventPublishingRunListener<br>
写入factories中
插手ServletContext初始化工作
implements ServletContextInitializer
自定义配置嵌入式Servlet容器
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>
mvc自定义配置
implements WebMvcConfigurer<br>
自定义事件
extends ApplicationEvent
ApplicationContext.publishEvent(“”)<br>
自定义事件监听器
容器事件
implements ApplicationListener<ApplicationEvent>
implements GenericApplicationListener
要想从容器创建开始就监听所有事件,在spring.factories配置<br>key=org.springframework.context.ApplicationListener
请求事件
extends RequestContextListener
插手容器启动时提供参数
implements ApplicationRunner
implements CommandLineRunner
3.ApplicationContextInitializer(系统初始化器
1.ApplicationContextInitializer 介绍
新建一个类 MyApplicationContextInitializer 并实现 ApplicationContextInitializer 接口
SpringBoot的main方法application.addInitializers
application.properties配置
SpringBoot的SPI扩展---META-INF/spring.factories中配置
4.监听器Listenter
SpringBoot框架事件
图片
<br>
获取监听器列表
图片<br>
<br>
触发机制
图片
<br>
自定监听器
5.Bean的创建
图片
<br>
6.Banner解析
7.计时器
StopWatch用来统计任务的耗时
8.启动类加载器
9.Spring Boot starter介绍以及自定义starter
1.starter介绍
2.自定义starter
pom文件添加spring-boot-autoconfigure和spring-boot-configuration-processor
创建PriceAutoConfiguration。增加注解EnableConfigurationProperties, ConditionalOnProperty
spring.factories中添加自动配置类实现
3.源码解析
图片
<br>
原理
4.webflux解析
WebFlux请求处理流程
图片<br>
<br>
0 条评论
下一页