热点新闻
springboot源码解析
2023-07-14 21:07  浏览:51  搜索引擎搜索“爱农网”
温馨提示:信息一旦丢失不一定找得到,请务必收藏信息以备急用!本站所有信息均是注册会员发布如遇到侵权请联系文章中的联系方式或客服删除!
联系我时,请说明是在爱农网看到的信息,谢谢。
展会发布 发布信息 广告合作 软文发布

1、初始化SpringApplication

启动的第一步,先调用SpringApplication的静态函数run方法,run方法会调用SpringApplication的有参构造方法来初始化SpringApplication。
而SpringApplication的初始化方法主要做以下几件事情:
1、推断当前 WEB 应用类型,一共有三种:
NONE:无内嵌的web容器启动,这种模式springboot需要运行于外部的web容器中
SERVLET:使用内嵌的web容器启动
REACTIVE:使用spring5的新特性,响应式启动

2、从meta-INF/spring.factories读取对应的ApplicationContextInitializer的类装配到集合中并去重
3、从meta-INF/spring.factories读取对应ApplicationListener的类装配到集合中并去重*

SpringApplication的构造函数实例化了 初始化上下文的各种接口ApplicationContextInitializer以及监听器ApplicationListener,要注意的是这里的实例化,并不像平时的Spring Components一样通过注解和扫包完成,而是通过一种不依赖Spring上下文的加载方法,这样才能在Spring完成启动前做各种配置。Spring的解决方法是以接口的全限定名作为key,实现类的全限定名作为value记录在项目的meta-INF/spring.factories文件中,然后通过SpringFactoriesLoader工具类提供静态方法进行类加载并缓存下来,spring.factories是Spring Boot的核心配置文件,目的是帮助Spring Boot完成自动化装配。

public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { ......................................... //推断当前 WEB 应用类型 this.webApplicationType = WebApplicationType.deduceFromClasspath(); //从"meta-INF/spring.factories"读取对应的ApplicationContextInitializer类的装配到集合中并去重 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); //从"meta-INF/spring.factories"读取对应ApplicationListener类的装配到集合中并去重 this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); //获取Main方法所在类,并赋值给mainApplicationClass this.mainApplicationClass = this.deduceMainApplicationClass(); }

spring.factories的部分内容:

# Initializers org.springframework.context.ApplicationContextInitializer=\ org.springframework.boot.autoconfigure.SharedmetadataReaderFactoryContextInitializer,\ org.springframework.boot.autoconfigure.logging.ConditionevaluationReportLoggingListener # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.boot.autoconfigure.BackgroundPreinitializer

2、执行SpringApplication.run启动容器

启动的步骤主要是以下几个步骤:
1、stopWatch.start():记录容器启动耗费的时间
2、this.getRunListeners(args):从"meta-INF/spring.factories"获取key为SpringApplicationRunListener的运行时监听器,其实就是EventPublishingRunListener监听器
3、listeners.starting() 向运行时监听器注册监听事件
4、ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments)根据监听器准备spring容器的环境变量
5、context = this.createApplicationContext()根据WEB 应用类型创建相应的容器,一共有三种:
NONE:AnnotationConfigApplicationContext
SERVLET:AnnotationConfigServletWebServerApplicationContext
REACTIVE:AnnotationConfigReactiveWebServerApplicationContext

6、this.prepareContext(context, environment, listeners, applicationArguments, printedBanner)这里主要是给容器设置前面准备好的环境变量,并且执行之前在spring.factories中读取的ApplicationContextInitializer类的initialize方法
7、this.refreshContext(context)刷新容器,这里比较重点后面单独分析
8、this.afterRefresh(context, applicationArguments)这里是空的方法,用于子类继承做一些容器启动后的拓展
9、监听器发布ApplicationStartedEvent事件和ApplicationReadyEvent事件

public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); //记录容器启动耗费的时间 stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); //从"meta-INF/spring.factories"获取key为SpringApplicationRunListener的监听器,其实就是EventPublishingRunListener监听器 SpringApplicationRunListeners listeners = this.getRunListeners(args); //遍历并集合中的监听器,并注册需要监听事件 listeners.starting(); Collection exceptionReporters; try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //准备spring容器的环境变量 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); Banner printedBanner = this.printBanner(environment); //根据WEB 应用类型创建相应的容器 context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); //这里主要是给容器设置前面准备好的环境变量,并且执行之前在spring.factories中读取的ApplicationContextInitializer类的initialize方法 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); //刷新容器 this.refreshContext(context); //这里是空的方法,用于子类继承做一些容器启动后的拓展 this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } //监听器发布ApplicationStartedEvent事件 listeners.started(context); try { listeners.running(context);//发布ApplicationReadyEvent事件 } ...................................... //返回容器上下文 return context; } private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); this.postProcessApplicationContext(context); this.applyInitializers(context); listeners.contextPrepared(context); ...................................... }

3、refresh()刷新容器

1、prepareRefresh()容器的预处理:记录启动时间,设置容器的状态,预留钩子方法给子类做属性设置,保存早期监听事件
2、obtainFreshBeanFactory()获取DefaultListableBeanFactory的作为工厂对象
3、prepareBeanFactory(beanFactory)设置工厂对象的属性,包括:类加载器、表达式解析器、添加后置处理器ApplicationContextAwareProcessor,系统环境属性Environment等
4、postProcessBeanFactory(beanFactory)钩子方法,预留给子类实现,在工厂对象准备刷新容器前做一些处理
5、invokeBeanFactoryPostProcessors(beanFactory)获取BeanDefinitionRegistryPostProcessor,遍历并根据优先级(继承order接口)执行其后置方法postProcessBeanDefinitionRegistry()方法。然后在获取所有的BeanFactoryPostProcessor的,再遍历并根据优先级(继承order接口)执行后置方法postProcessBeanFactory(),由此可见后置处理器BeanDefinitionRegistryPostProcessor是在BeanFactoryPostProcessor之前执行
6、registerBeanPostProcessors(beanFactory)获取所有的BeanPostProcessor,例如:InstantiationAwareBeanPostProcessor等,根据优先级(继承order接口)将所有的BeanPostProcessor注册到工厂对象中
7、initMessageSource()进行国际化
8、initApplicationEventMulticaster() 初始化的事件派发器
9、onRefresh()钩子方法,预留给子类进行拓展处理,其中springboot的web容器AnnotationConfigServletWebServerApplicationContext会在这里启动Tomcat
10、registerListeners()注册事件监听器,监听器需要实现 ApplicationListener 接口
11、finishBeanFactoryInitialization(beanFactory)初始化所有的单实例bean,主要方法在工厂对象的preInstantiateSingletons()方法,先获取RootBeanBefinition,在判断是否是factoryBean,是则调用factoryBean的方法创建bean,不是则调用getBean()方法进行bean的创建,getBean()方法是spring创建bean的核心类,我之前在spring源码分析那里分析过,这里不再赘述,主要流程就先从缓存中获取bean,获取不到就从头开始创建bean,并经过bean的实例化、属性赋值、初始化的生命周期,中间调用Aware类的方法和上面注册的BeanPostProcessor的前后置方法,完成IOC创建
12、finishRefresh()容器调用LifecycleProcessor生命周期处理器的onRefresh()和onClose()方法,然后调用publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this)))发布容器刷新完成事件

public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh"); this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process"); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); beanPostProcess.end(); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var10) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10); } this.destroyBeans(); this.cancelRefresh(var10); throw var10; } finally { this.resetCommonCaches(); contextRefresh.end(); } } } protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { ....................................... beanFactory.preInstantiateSingletons(); } public void preInstantiateSingletons() throws BeansException { List<String> beanNames = new ArrayList(this.beanDefinitionNames); Iterator var2 = beanNames.iterator(); while(true) { String beanName; Object bean; do { while(true) { RootBeanDefinition bd; do { do { do { if (!var2.hasNext()) { var2 = beanNames.iterator(); while(var2.hasNext()) { beanName = (String)var2.next(); Object singletonInstance = this.getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged(() -> { smartSingleton.afterSingletonsInstantiated(); return null; }, this.getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } return; } beanName = (String)var2.next(); bd = this.getMergedLocalBeanDefinition(beanName); } while(bd.isAbstract()); } while(!bd.isSingleton()); } while(bd.isLazyInit()); if (this.isFactoryBean(beanName)) { bean = this.getBean("&" + beanName); break; } this.getBean(beanName); } } while(!(bean instanceof FactoryBean)); FactoryBean<?> factory = (FactoryBean)bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { SmartFactoryBean var10000 = (SmartFactoryBean)factory; ((SmartFactoryBean)factory).getClass(); isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext()); } else { isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit(); } if (isEagerInit) { this.getBean(beanName); } } }

4、springboot的自动化装配

@SpringBootApplication上的注解@EnableAutoConfiguration,通过@import({AutoConfigurationimportSelector.class})注入AutoConfigurationimportSelector,AutoConfigurationimportSelector通过调用getAutoConfigurationEntry方法,方法中会调用getCandidateConfigurations方法,然后通过SpringFactoriesLoader.loadFactoryNames方法,从meta-INF/spring.factories读取EnableAutoConfiguration的类为key,value为需要自动装配的xxxConfiguration配置类的数组,通过SpringFactoriesLoader机制创建对应的bean,注入到容器中,完成了自动装配。

这本来需要在spring的xml配置文件中去配置bean的操作就免去了 ,也就是说我们可以事先在xxxConfiguration中做好各种默认配置,然后通过加入到spring.factories中让spring自动读取并装配,实现了starter默认配置达到了约定大于配置的思想,这就是也就是springboot的自动装配

简单的流程如下:@EnableAutoConfiguration->@import({AutoConfigurationimportSelector.class})->SpringFactoriesLoader.loadFactoryNames->meta-INF/spring.factories->org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxxConfiguration,xxxConfiguration....

@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @documented @Inherited @AutoConfigurationPackage @import({AutoConfigurationimportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }

AutoConfigurationimportSelector类及对应的SpringFactoriesLoader.loadFactoryNames及SpringFactoriesLoader.loadSpringFactories方法

public class AutoConfigurationimportSelector implements DeferredimportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { protected AutoConfigurationimportSelector.AutoConfigurationEntry getAutoConfigurationEntry(Annotationmetadata annotationmetadata) { if (!this.isEnabled(annotationmetadata)) { return EMPTY_ENTRY; } else { AnnotationAttributes attributes = this.getAttributes(annotationmetadata); List<String> configurations = this.getCandidateConfigurations(annotationmetadata, attributes); configurations = this.removeDuplicates(configurations); Set<String> exclusions = this.getExclusions(annotationmetadata, attributes); this.checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = this.getConfigurationClassFilter().filter(configurations); this.fireAutoConfigurationimportEvents(configurations, exclusions); return new AutoConfigurationimportSelector.AutoConfigurationEntry(configurations, exclusions); } } protected List<String> getCandidateConfigurations(Annotationmetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in meta-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; } } public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { String factoryTypeName = factoryType.getName(); return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); } private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { Enumeration<URL> urls = classLoader != null ? classLoader.getResources("meta-INF/spring.factories") : ClassLoader.getSystemResources("meta-INF/spring.factories"); linkedMultiValueMap result = new linkedMultiValueMap(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryTypeName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryImplementationName = var9[var11]; result.add(factoryTypeName, factoryImplementationName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [meta-INF/spring.factories]", var13); } } }

# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\

发布人:566b****    IP:117.173.23.***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发