国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

spring boot容器啟動流程

2024-07-13 10:17:15
字體:
來源:轉載
供稿:網友

 

一、前言

spring cloud大行其道的當下,如果不了解基本原理那么是很糾結的(看見的都是 約定大于配置 ,但是原理呢?為什么要這么做?)。spring cloud是基于spring boot快速搭建的,今天咱們就看看spring boot容器啟動流程。(本文不講解如何快速啟動spring boot,那些直接官方看即可, 官網文檔飛機票 )

二、容器啟動

spring boot一般是 指定容器啟動main方法,然后以命令行方式啟動Jar包 ,如下圖:

 @SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

這里核心關注2個東西:

1.@SpringBootApplication注解

2. SpringApplication.run()靜態方法

下面我們就分別探究這兩塊內容。

2.1 @SpringBootApplication注解

源碼如下:  

 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {

核心注解:

@SpringBootConfiguration(實際就是個@Configuration):表示這是一個JavaConfig配置類,可以在這個類中自定義bean,依賴關系等。-》這個是spring-boot特有的注解,常用到。

@EnableAutoConfiguration:借助@Import的幫助,將所有符合自動配置條件的bean定義加載到IoC容器(建議放在根包路徑下,這樣可以掃描子包和類)。-》這個需要詳細深挖!

@ComponentScan:spring的自動掃描注解,可定義掃描范圍,加載到IOC容器。-》這個不多說,spring的注解大家肯定眼熟

其中@EnableAutoConfiguration這個注解的源碼:

 @SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {

核心是一個EnableAutoConfigurationImportSelector類圖如下:

 spring,boot,容器啟動,容器

核心方法在頂級接口 ImportSelector 的 selectImports() ,源碼如下:

 @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } try { //1.從META-INF/spring-autoconfigure-metadata.properties文件中載入483條配置屬性(有一些有默認值), AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader  .loadMetadata(this.beanClassLoader); AnnotationAttributes attributes = getAttributes(annotationMetadata);//2.獲取注解屬性 List<String> configurations = getCandidateConfigurations(annotationMetadata,//3.獲取97個自動配置類  attributes); configurations = removeDuplicates(configurations);//4.移除重復的 configurations = sort(configurations, autoConfigurationMetadata);//5.排序 Set<String> exclusions = getExclusions(annotationMetadata, attributes);//6.獲取需要排除的 checkExcludedClasses(configurations, exclusions);//7.校驗排除類 configurations.removeAll(exclusions);//8.刪除所有需要排除的 configurations = filter(configurations, autoConfigurationMetadata);//9.過濾器OnClassCondition(注解中配置的當存在某類才生效) fireAutoConfigurationImportEvents(configurations, exclusions);//10.觸發自動配置導入監聽事件 return configurations.toArray(new String[configurations.size()]); } catch (IOException ex) { throw new IllegalStateException(ex); } }

這里注意3個核心方法:

1) loadMetadata 加載配置

其實就是用類加載器去加載: META-INF/spring-autoconfigure-metadata.properties (spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar) 文件中定義的配置,返回PropertiesAutoConfigurationMetadata(實現了AutoConfigurationMetadata接口,封裝了屬性的get set方法)

2) getCandidateConfigurations 獲取默認支持的自動配置類名列表

自動配置靈魂方法, SpringFactoriesLoader.loadFactoryNames 從 META-INF/spring.factories (spring-boot-autoconfigure-1.5.9.RELEASE-sources.jar)文件中獲取自動配置類key=EnableAutoConfiguration.class的配置。 

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {//話說這里2個入參沒啥用啊...誰來給我解釋一下... List<String> configurations = SpringFactoriesLoader.loadFactoryNames(  getSpringFactoriesLoaderFactoryClass(), 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; } //返回的是EnableAutoConfiguration類 protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }

實際獲取了什么? spring.factories 文件如下,實際獲取了 # Auto Configure 自動配置模塊的所有類。

# Initializersorg.springframework.context.ApplicationContextInitializer=/org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,/org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer# Application Listenersorg.springframework.context.ApplicationListener=/org.springframework.boot.autoconfigure.BackgroundPreinitializer# Auto Configuration Import Listenersorg.springframework.boot.autoconfigure.AutoConfigurationImportListener=/org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener# Auto Configuration Import Filtersorg.springframework.boot.autoconfigure.AutoConfigurationImportFilter=/org.springframework.boot.autoconfigure.condition.OnClassCondition# 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.cloud.CloudAutoConfiguration,/org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,/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.CassandraRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,/org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,/org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,/org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,/org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,/org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,/org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,/org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,/org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,/org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,/org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,/org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,/org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,/org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,/org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,/org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,/org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,/org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,/org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,/org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,/org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,/org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,/org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,/org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,/org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,/org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,/org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,/org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,/org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,/org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,/org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,/org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,/org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,/org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,/org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,/org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,/org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,/org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,/org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,/org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,/org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,/org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,/org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,/org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,/org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,/org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,/org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,/org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,/org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,/org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,/org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,/org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,/org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,/org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,/org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,/org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,/org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,/org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,/org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,/org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,/org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,/org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,/org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,/org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,/org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,/org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,/org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,/org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,/org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,/org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,/org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,/org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,/org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,/org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,/org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration# Failure analyzersorg.springframework.boot.diagnostics.FailureAnalyzer=/org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,/org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,/org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer# Template availability providersorg.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=/org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,/org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,/org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,/org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,/org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider

3)filter過濾器 根據 OnClassCondition 注解把不滿足條件的過濾掉

 private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) { long startTime = System.nanoTime(); String[] candidates = configurations.toArray(new String[configurations.size()]); boolean[] skip = new boolean[candidates.length]; boolean skipped = false; //獲取需要過濾的自動配置導入攔截器,spring.factories配置中就一個:org.springframework.boot.autoconfigure.condition.OnClassCondition for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) { invokeAwareMethods(filter); boolean[] match = filter.match(candidates, autoConfigurationMetadata); for (int i = 0; i < match.length; i++) {  if (!match[i]) {  skip[i] = true;  skipped = true;  } } } if (!skipped) {//多條件只要有一個不匹配->skipped = true,全部匹配-》skipped = false->直接返回 return configurations; } List<String> result = new ArrayList<String>(candidates.length); for (int i = 0; i < candidates.length; i++) { if (!skip[i]) {//匹配-》不跳過-》添加進result  result.add(candidates[i]); } } if (logger.isTraceEnabled()) { int numberFiltered = configurations.size() - result.size(); logger.trace("Filtered " + numberFiltered + " auto configuration class in "  + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime)  + " ms"); } return new ArrayList<String>(result); }

2.2 SpringApplication .run()靜態方法

SpringApplication.run 

 public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args);//1.獲取監聽器 listeners.starting();-->啟動! try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(  args); ConfigurableEnvironment environment = prepareEnvironment(listeners,//2.準備好環境,觸發ApplicationEnvironmentPreparedEvent事件  applicationArguments); Banner printedBanner = printBanner(environment);//打印啟動提示字符,默認spring的字符圖 context = createApplicationContext();//實例化一個可配置應用上下文 analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments,//3.準備上下文  printedBanner); refreshContext(context);//4.刷新上下文 afterRefresh(context, applicationArguments);//5.刷新上下文后 listeners.finished(context, null);--關閉! stopWatch.stop(); if (this.logStartupInfo) {  new StartupInfoLogger(this.mainApplicationClass)  .logStarted(getApplicationLog(), stopWatch); } return context; } catch (Throwable ex) { handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } }

1. getRunListeners 獲取監聽器( SpringApplicationRunListeners )

實際是 SpringApplicationRunListener 類

 private SpringApplicationRunListeners getRunListeners(String[] args) { Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class }; return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)); } private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); } private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // 使用Set確保的字符串的唯一性 Set<String> names = new LinkedHashSet<String>( SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 1.載入工廠名稱集合 List<T> instances = createSpringFactoriesInstances(type, parameterTypes,// 2.創建工廠實例 classLoader, args, names); AnnotationAwareOrderComparator.sort(instances);// 排序 return instances; }

1.1 載入工廠名稱(loadFactoryNames)

當前類的類加載器從 META-INF/spring.factories 文件中獲取SpringApplicationRunListener類的配置

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :  ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); List<String> result = new ArrayList<String>(); while (urls.hasMoreElements()) {  URL url = urls.nextElement();  Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));  String factoryClassNames = properties.getProperty(factoryClassName);  result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +  "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } }

上圖,獲取到工廠類名后,下面來看看META-INF/spring.factories中定義了啥:

# PropertySource Loadersorg.springframework.boot.env.PropertySourceLoader=/org.springframework.boot.env.PropertiesPropertySourceLoader,/org.springframework.boot.env.YamlPropertySourceLoader# Run Listeners 這里呢,看這里!!!!org.springframework.boot.SpringApplicationRunListener=/org.springframework.boot.context.event.EventPublishingRunListener# Application Context Initializersorg.springframework.context.ApplicationContextInitializer=/org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,/org.springframework.boot.context.ContextIdApplicationContextInitializer,/org.springframework.boot.context.config.DelegatingApplicationContextInitializer,/org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer# Application Listenersorg.springframework.context.ApplicationListener=/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# Environment Post Processorsorg.springframework.boot.env.EnvironmentPostProcessor=/org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,/org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor# Failure Analyzersorg.springframework.boot.diagnostics.FailureAnalyzer=/org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,/org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,/org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,/org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,/org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,/org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,/org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer# FailureAnalysisReportersorg.springframework.boot.diagnostics.FailureAnalysisReporter=/org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

哇,都是些類全名稱,且key都是接口,value都是實現類。我們根據key=“ org.springframework.boot.SpringApplicationRunListener ”查詢得到實現類value=" org.springframework.boot.context.event.EventPublishingRunListener" 事件發布啟動監聽器 , 一猜也知道肯定要用” 反射 ”根據類名獲取類實例,下面很快得到驗證...

1.2 創建spring工廠實例(createSpringFactoriesInstances)

根據第一步得到的Set<String> names(SpringApplicationRunListener的唯一實現類 EventPublishingRunListener )生成" 事件發布啟動監聽器 " 工廠實例

 @SuppressWarnings("unchecked") private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) { List<T> instances = new ArrayList<T>(names.size()); for (String name : names) { try {  Class<?> instanceClass = ClassUtils.forName(name, classLoader);// 利用反射獲取類  Assert.isAssignable(type, instanceClass);  Constructor<?> constructor = instanceClass  .getDeclaredConstructor(parameterTypes);// 得到構造器  T instance = (T) BeanUtils.instantiateClass(constructor, args);// 根據構造器和參數構造實例  instances.add(instance); } catch (Throwable ex) {  throw new IllegalArgumentException(  "Cannot instantiate " + type + " : " + name, ex); } } return instances; }

準備上下文

 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { context.setEnvironment(environment); postProcessApplicationContext(context);//單例一個BeanNameGenerator,把ResourceLoader設置進應用上下文 applyInitializers(context);//執行初始化器 listeners.contextPrepared(context);// 監聽器執行上下文"已準備好"方法 if (this.logStartupInfo) { logStartupInfo(context.getParent() == null); logStartupProfileInfo(context); }  // 添加spring boot特殊單例bean context.getBeanFactory().registerSingleton("springApplicationArguments",  applicationArguments); if (printedBanner != null) { context.getBeanFactory().registerSingleton("springBootBanner", printedBanner); } // 載入資源 Set<Object> sources = getSources(); Assert.notEmpty(sources, "Sources must not be empty"); load(context, sources.toArray(new Object[sources.size()])); listeners.contextLoaded(context);// 監聽器執行"上下文已加載"方法 }

刷新上下文

 private void refreshContext(ConfigurableApplicationContext context) { refresh(context);//核心類 if (this.registerShutdownHook) { try { context.registerShutdownHook();//注冊關閉鉤子,容器關閉時執行 } catch (AccessControlException ex) { // Not allowed in some environments. } } } protected void refresh(ApplicationContext applicationContext) { Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext); ((AbstractApplicationContext) applicationContext).refresh(); }

最終執行的是AbstractApplicationContext抽象類的 refresh 方法。

 public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //準備刷新的上下文環境,例如對系統屬性或者環境變量進行準備及驗證。 prepareRefresh(); //啟動子類的refreshBeanFactory方法.解析xml ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //為BeanFactory配置容器特性,例如類加載器、事件處理器等. prepareBeanFactory(beanFactory); try {  //設置BeanFactory的后置處理. 空方法,留給子類拓展用。   postProcessBeanFactory(beanFactory);  //調用BeanFactory的后處理器, 這些后處理器是在Bean定義中向容器注冊的.   invokeBeanFactoryPostProcessors(beanFactory);  //注冊Bean的后處理器, 在Bean創建過程中調用.   registerBeanPostProcessors(beanFactory);  //初始化上下文中的消息源,即不同語言的消息體進行國際化處理   initMessageSource();  //初始化ApplicationEventMulticaster bean,應用事件廣播器  initApplicationEventMulticaster();  //初始化其它特殊的Bean, 空方法,留給子類拓展用。   onRefresh();  //檢查并向容器注冊監聽器Bean  registerListeners();  //實例化所有剩余的(non-lazy-init) 單例Bean.  finishBeanFactoryInitialization(beanFactory);  //發布容器事件, 結束refresh過程.   finishRefresh(); } catch (BeansException ex) {  if (logger.isWarnEnabled()) {  logger.warn("Exception encountered during context initialization - " +  "cancelling refresh attempt: " + ex);  }  //銷毀已經創建的單例Bean, 以避免資源占用.  destroyBeans();  //取消refresh操作, 重置active標志.   cancelRefresh(ex);  // Propagate exception to caller.  throw ex; } finally {  //重置Spring的核心緩存  resetCommonCaches(); } } }

刷新完上下文后

spring boot提供的2個供用戶自己拓展的接口: ApplicationRunner和 CommandLineRunner。可以在容器啟動完畢后(上下文刷新后)執行,做一些類似數據初始化的操作。

 private void callRunners(ApplicationContext context, ApplicationArguments args) { List<Object> runners = new ArrayList<Object>(); runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());//從上下文中獲取ApplicationRunner類型的bean runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());//從上下文中獲取CommandLineRunner類型的bean AnnotationAwareOrderComparator.sort(runners);//排序 for (Object runner : new LinkedHashSet<Object>(runners)) { if (runner instanceof ApplicationRunner) {  callRunner((ApplicationRunner) runner, args);//執行 } if (runner instanceof CommandLineRunner) {  callRunner((CommandLineRunner) runner, args); } } }

兩個區別在于入參不同,根據實際情況自己選擇。

 public interface CommandLineRunner { void run(String... args) throws Exception; } public interface ApplicationRunner { void run(ApplicationArguments args) throws Exception; }

CommandLineRunner中執行參數是原始的 java啟動類main方法的String[] args字符串數組參數; ApplicationRunner中的參數經過處理提供一些方法例如:

 List<String> getOptionValues(String name);

根據名稱獲取值list,java 啟動命令中 --foo=bar --foo=baz,則根據foo參數名返回list ["bar", "baz"]

三、總結

spring,boot,容器啟動,容器

按照前面的分析,Spring-boot容器啟動流程總體可劃分為2部分:

1) 執行注解 :掃描指定范圍下的bean、載入自動配置類對應的bean加載到IOC容器。

2)man方法中具體SpringAppliocation.run() ,全流程貫穿SpringApplicationEvent,有6個子類:

ApplicationFailedEvent.classApplicationPreparedEvent.classApplicationReadyEvent.classApplicationStartedEvent.classApplicationStartingEvent.classSpringApplicationEvent.class

這里用到了很經典的 spring事件驅動模型 ,飛機票: Spring事件驅動模型和觀察者模式

類圖如下:

spring,boot,容器啟動,容器

如上圖,就是一個經典spring 事件驅動模型,包含3種角色:事件發布者、事件、監聽者。對應到spring-boot中就是:

1 .EventPublishingRunListener 這個類封裝了 事件發布 ,

2. SpringApplicationEvent 是spring-boot中定義的事件(上面說的6種事件),繼承自 ApplicationEvent (spring中定義的)

3. 監聽者 spring-boot并沒有實現針對上述6種事件的監聽者(我沒找到...), 這里用戶可以自己實現監聽者(上述6種事件)來注入spring boot容器啟動流程,觸發相應的事件。

例如:實現ApplicationListener<ApplicationReadyEvent>這個接口,在容器啟動完畢時最后一步listener.finished時,如果啟動沒有異常,就會執行!可以做一些數據初始化之類的操作。

總結

以上所述是小編給大家介紹的spring boot容器啟動的相關知識,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 酒泉市| 梅州市| 邛崃市| 江川县| 遂昌县| 东丽区| 宁波市| 关岭| 承德县| 泸水县| 桃江县| 墨玉县| 阳新县| 昭苏县| 东宁县| 丰顺县| 长垣县| 织金县| 安阳市| 固阳县| 岳阳市| 资溪县| 黔西| 郓城县| 唐山市| 株洲市| 武定县| 禹州市| 禄劝| 扎鲁特旗| 拜城县| 陆河县| 威信县| 江津市| 奎屯市| 长乐市| 隆尧县| 南丹县| 金寨县| 长武县| 侯马市|