springboot源码流程解析
2020-06-01 21:51:36 121 举报
AI智能生成
springboot源码流程图解析
作者其他创作
大纲/内容
应用
自定义运行监听器
implements SpringApplicationRunListener
extends EventPublishingRunListener
extends EventPublishingRunListener
写入factories中
插手ServletContext初始化工作
implements ServletContextInitializer
自定义配置嵌入式Servlet容器
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>
mvc自定义配置
implements WebMvcConfigurer
自定义事件
extends ApplicationEvent
ApplicationContext.publishEvent(“”)
自定义事件监听器
容器事件
implements ApplicationListener<ApplicationEvent>
implements GenericApplicationListener
要想从容器创建开始就监听所有事件,在spring.factories配置
key=org.springframework.context.ApplicationListener
key=org.springframework.context.ApplicationListener
请求事件
extends RequestContextListener
插手容器启动时提供参数
implements ApplicationRunner
implements CommandLineRunner
@SpringBootApplication
@SpringBootConfiguration
@Configuration
@ComponentScan(excludeFilters = {x,x})
AutoConfigurationExcludeFilter
TypeExcludeFilter
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationPackages.Registrar.class)
#registerBeanDefinitions
@Import(AutoConfigurationImportSelector.class)
#selectImports(AnnotationMetadata annotationMetadata)
#isEnabled(AnnotationMetadata metadata)
#getAutoConfigurationEntry(AnnotationMetadata annotationMetadata)
#getCandidateConfigurations(annotationMetadata, attributes)
启动流程
SpringApplication.run(HibikiApplication.class, args);
--run(new Class<?>[] { primarySource }, args)
----new SpringApplication(primarySources).run(args)
--run(new Class<?>[] { primarySource }, args)
----new SpringApplication(primarySources).run(args)
this(resourceLoader:null, primarySources);
this.resourceLoader = resourceLoader;
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
REACTIVE
NONE
SERVLET
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
getSpringFactoriesInstances(ApplicationContextInitializer.class,new Class<?>[] {})
getClassLoader()
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader))
--loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList())
--loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList())
(List)loadSpringFactories(classLoader)
getOrDefault(factoryTypeName, Collections.emptyList()
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names)
setInitializers
--this.initializers = new ArrayList<>(initializers)
--this.initializers = new ArrayList<>(initializers)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
--this.listeners = new ArrayList<>(listeners);
--this.listeners = new ArrayList<>(listeners);
this.mainApplicationClass = deduceMainApplicationClass();
#run(args)
ConfigurableApplicationContext context = null
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>()
SpringApplicationRunListeners listeners = getRunListeners(args);
实例化并封装若干个EventPublishingRunListener
实例化并封装若干个EventPublishingRunListener
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args))
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args))
listeners.starting()
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
--multicastEvent(event, resolveDefaultEventType(event));
发布容器ApplicationStartingEvent的事件
--multicastEvent(event, resolveDefaultEventType(event));
发布容器ApplicationStartingEvent的事件
RestartApplicationListener#onApplicationStartingEvent
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
invokeListener(listener, event);
}
invokeListener(listener, event);
}
#getApplicationListeners
根据sourceType和EventType选出支持的监听器
根据sourceType和EventType选出支持的监听器
#invokeListener
--doInvokeListener
----listener.onApplicationEvent(event);
--doInvokeListener
----listener.onApplicationEvent(event);
LoggingApplicationListener
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
根据this.webApplicationType创建一个对应类型的environment。Servlet对应StandardServletEnvironment()
将命令行参数封装到SimpleCommandLinePropertySource,加入environment
从系统配置中获取并配置Profile
添加ConfigurationPropertySourcesPropertySource
触发ApplicationEnvironmentPreparedEvent事件
BootstrapApplicationListener
ConfigFileApplicationListener
实例化所有EnvironmentPostProcessor
调用所有后置处理器的#postProcessEnvironment
EnvironmentPostProcessorApplicationListener
调用所有的EnvironmentPostProcessor
LoggingApplicationListener
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
若没有显示指定容器的类型,则根据this.webApplicationType创建class
若为SERVLET,创建AnnotationConfigServletWebServerApplicationContext,反射实例化
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
context.setEnvironment(environment)
postProcessApplicationContext(context);
applyInitializers(context);
循环依次ApplicationContextInitializer#initialize(context)
listeners.contextPrepared(context);
log
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (this.lazyInitialization)默认false,可在yaml配置main:lazy-initialization:true
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor())
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor())
Set<Object> sources = getAllSources();
load(context, sources.toArray(new Object[0]))
listeners.contextLoaded(context);
refreshContext(context);
refresh((ApplicationContext) context);
--ServletWebServerApplicationContext#refresh
--ServletWebServerApplicationContext#refresh
大部分与普通springioc容器流程相同,详情见springioc流程分析
不同点
#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
#invokeBeanFactoryPostProcessors
#registerBeanPostProcessors
ConfigurationPropertiesBindingPostProcessor
webServerFactoryCustomizerBeanPostProcessor
errorPageRegistrarBeanPostProcessor
#Onfresh
GenericWebApplicationContext#Onfresh
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
ServletWebServerApplicationContext#Onfresh
createWebServer()
ServletWebServerFactory factory = getWebServerFactory();
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class)
--return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class)
--return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class)
this.webServer = factory.getWebServer(this::selfInitialize);
this::selfInitialize: 传入方法引用,匿名函数,在之后webServer初始化时调用
--selfInitialize(ServletContext servletContext)
--selfInitialize(ServletContext servletContext)
prepareWebApplicationContext(servletContext);
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);
--registerEnvironmentBeans(bf, sc, (ServletConfig)null);
----bf.registerSingleton("servletContext", servletContext);
---- bf.registerSingleton(“servletConfig”, servletConfig);
----bf.registerSingleton("contextParameters", Collections.unmodifiableMap(attributeMap));
----bf.registerSingleton("contextAttributes", Collections.unmodifiableMap(attributeMap));
--registerEnvironmentBeans(bf, sc, (ServletConfig)null);
----bf.registerSingleton("servletContext", servletContext);
---- bf.registerSingleton(“servletConfig”, servletConfig);
----bf.registerSingleton("contextParameters", Collections.unmodifiableMap(attributeMap));
----bf.registerSingleton("contextAttributes", Collections.unmodifiableMap(attributeMap));
for (ServletContextInitializer beans : getServletContextInitializerBeans())
beans.onStartup(servletContext);
beans.onStartup(servletContext);
getServletContextInitializerBeans()
--return new ServletContextInitializerBeans(getBeanFactory());
--return new ServletContextInitializerBeans(getBeanFactory());
addServletContextInitializerBeans(beanFactory);
实例化配置所有ServletContextInitializer的Bean
ServletRegistrationBean、FilterRegistrationBean
ServletRegistrationBean、FilterRegistrationBean
dispatcherServletRegistration
DelegatingFilterProxyRegistrationBean
SpringSecurity
SpringSecurity
addAdaptableBeans(beanFactory);
#onStartup
DispatcherServletRegistrationBean
characterEncodingFilter
formContentFilter
requestContextFilter
getWebServer(ServletContextInitializer... initializers)
if (this.disableMBeanRegistry)
Registry.disableRegistry();
Registry.disableRegistry();
Tomcat tomcat = new Tomcat();
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
Http11NioProtocol
tomcat.getService().addConnector(connector);
#getService
return getServer().findServices()[0]
#getServer
server = new StandardServer();
server.setCatalinaBase(baseFile);
server.setCatalinaHome(baseFile);
Service service = new StandardService();
server.addService(service);
return server;
#addConnector
connector.setService(this);
#customizeConnector(connector);
tomcat.setConnector(connector);
configureEngine(tomcat.getEngine());
prepareContext(tomcat.getHost(), initializers);
TomcatEmbeddedContext context = new TomcatEmbeddedContext();
context.setName(getContextPath());
context.setDisplayName(getDisplayName());
context.setPath(getContextPath());
context.setDisplayName(getDisplayName());
context.setPath(getContextPath());
File docBase = createTempDir("tomcat-docbase");
ontext.setDocBase(docBase.getAbsolutePath());
addDefaultServlet(context);
if (shouldRegisterJspServlet()) {
addJspServlet(context);
addJasperInitializer(context);
}
addJspServlet(context);
addJasperInitializer(context);
}
configureContext(context, initializersToUse);
postProcessContext(context);
return getTomcatWebServer(tomcat);
--return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
--return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
initialize();
this.tomcat.start();
注册webServerGracefulShutdown的单例
注册webServerStartStop的单例
GenericWebApplicationContext#initPropertySources();
ConfigurableEnvironment env = this.getEnvironment();
env.initPropertySources(this.servletContext, (ServletConfig)null);
--StandardServletEnvironment#initPropertySources(ServletContext servletContext, ServletConfig servletConfig)
----WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
--StandardServletEnvironment#initPropertySources(ServletContext servletContext, ServletConfig servletConfig)
----WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);
sources.replace("servletContextInitParams", new ServletContextPropertySource("servletContextInitParams", servletContext));
sources.replace("servletConfigInitParams", new ServletConfigPropertySource("servletConfigInitParams", servletConfig));
#registerListeners
#finishBeanFactoryInitialization
#finishRefresh
getLifecycleProcessor().onRefresh();
DefaultLifecycleProcessor#startBeans(true);
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
webServerStartStopLifeCircle#start
this.webServer.start();
this.running = true;
发布ServletWebServerInitializedEvent事件
webServerGracefulShutdownLifeCircle
this.running = true;
根据各个bean不同的应用阶段分组
调用LifecycleGroup中的所有Lifecycle的start方法
this.running = true;
this.webServer.start()
context.registerShutdownHook();
afterRefresh(context, applicationArguments);
listeners.started(context);
ApplicationStartedEvent、AvailabilityChangeEvent
ApplicationStartedEvent、AvailabilityChangeEvent
callRunners(context, applicationArguments);
调用上下文中所有ApplicationRunner,CommandLineRunner的Bean的run方法
调用上下文中所有ApplicationRunner,CommandLineRunner的Bean的run方法
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
循环callRunner((CommandLineRunner) runner, args);
listeners.running(context);
ApplicationReadyEvent、AvailabilityChangeEvent
ApplicationReadyEvent、AvailabilityChangeEvent
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args)
参数封装,也就是在命令行下启动应用带的参数,如--server.port=9000
参数封装,也就是在命令行下启动应用带的参数,如--server.port=9000
0 条评论
下一页