作为一个高级程序员,一定要多看开源框架源码。从大师那里学的一些编程技巧。因此将自己看SpringBoot的心得总结一下。
为了更加直观的描述SpringBoot的启动流程,这里给出SpringBoot的启动时序图,本文将根据这个时序图作详细描述。
很容易知道SpringBoot的启动类为SpringApplication。从SpringBoot的源码看他的启动方法就两个大的方法分别是initialize(source)和run(args)方法。
initialize(source)
initialize方法主要是初始化ApplicationListener.class接口和ApplicationContextInitializer.class接口这两类对象。
这两步的处理方式为通过扫描包下面的META-INFO/spring.factories文件。读取org.springframework.context.ApplicationContextInitializer和org.springframework.context.ApplicationListener两个键的值来构建ApplicationContextInitializer和ApplicationListener。
扫描完成后的上下文构造器有
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
org.springframework.boot.context.ContextIdApplicationContextInitializer
org.springframework.boot.context.config.DelegatingApplicationContextInitializer
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
扫描完成后的监听器有
org.springframework.boot.ClearCachesApplicationListener
org.springframework.boot.builder.ParentContextCloserApplicationListener
org.springframework.boot.context.FileEncodingApplicationListener
org.springframework.boot.context.config.AnsiOutputApplicationListener
org.springframework.boot.context.config.ConfigFileApplicationListener
org.springframework.boot.context.config.DelegatingApplicationListener
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
org.springframework.boot.logging.ClasspathLoggingApplicationListener
org.springframework.boot.logging.LoggingApplicationListener
org.springframework.boot.autoconfigure.BackgroundPreinitializer
run(args)
run方法可以总结为如下流程
一、记录应用启动时间
二、启动SpringApplicationRunListeners这一类的监听器
扫描方式与上面初始化的方法一致扫描结果为org.springframework.boot.context.event.EventPublishingRunListener内部得listeners为EventPublishingRunListener。主要执行上面初始化监器的onApplicationEvent()方法响应ApplicationStartedEvent事件。
三、准备SpringBoot的环境prepareEnvironment
主要执行上面初始化监器的onApplicationEvent()方法响应ApplicationEnvironmentPreparedEvent事件。
四、打印SpringBoot的启动Banner即printBanner
五、创建SpringBoot的应用上下文createApplicationContext
此处实例化AnnotationConfigEmbeddedWebApplicationContext对象创建了this.reader = new AnnotatedBeanDefinitionReader(this);this.scanner = new ClassPathBeanDefinitionScanner(this);这两个Bean定业读取器和扫描器。
六、准备SpringBoot的上下文需要的资源prepareContext
此处创建ClassPathBeanDefinitionScanner进行类加载Load开始加载SpringApplication的启动类。然后发布ApplicationPreparedEvent事件
七、进一步完善Context里面的内容refreshContext
这里主要加载业务Bean
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
其中invokeBeanFactoryPostProcessors(beanFactory)进行启动类注解扫描。
doProcessConfigurationClass方法
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
其中doScan进行包扫描
return scanner.doScan(StringUtils.toStringArray(basePackages));
如果是Servlet应用则在initApplicationEventMulticaster注册Servlet和filiter()
在finishBeanFactoryInitialization()创建请求映射Mapper
在finishRefresh启动Tomcat操作。
启动Tomcat等操作
八、处理Context完全创建后的事情afterRefresh
执行callRunners
九、记录应用启动时间花费
十、打印应用启动成功后的日志信息。