亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 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教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲国产又黄又爽女人高潮的| 欧美激情小视频| 欧美在线一区二区三区四| 成人欧美一区二区三区在线湿哒哒| 欧美精品videos性欧美| 久久久久久久香蕉网| 日韩亚洲欧美中文高清在线| 韩国19禁主播vip福利视频| 色偷偷av亚洲男人的天堂| 日本久久精品视频| 日韩av免费在线观看| 亚洲欧美综合精品久久成人| 日韩亚洲成人av在线| 中文字幕亚洲无线码a| 亚洲午夜精品久久久久久久久久久久| 亚洲精品电影久久久| 国产精品电影一区| 久久久久久尹人网香蕉| 亚洲成色777777女色窝| 久久久影视精品| 欧洲亚洲免费视频| 色偷偷av一区二区三区| 亚洲精品在线91| 夜夜嗨av色综合久久久综合网| 欧美精品在线观看| 欧美激情videos| 性日韩欧美在线视频| 97香蕉超级碰碰久久免费的优势| 国产成人精品一区二区三区| 亚洲精选一区二区| 国产精品激情av电影在线观看| 日韩三级影视基地| 国产精品精品视频一区二区三区| 久久成人一区二区| 国产精品成人观看视频国产奇米| 欧美高清在线播放| 久久久久久久久91| 欧美午夜视频一区二区| 日韩在线观看电影| 精品视频中文字幕| 久久精品亚洲热| 久久久久久91香蕉国产| 日韩免费电影在线观看| 久久久久国产精品免费网站| 一区二区三区视频观看| 亚洲国产成人久久| 亚洲人成网站999久久久综合| 精品亚洲va在线va天堂资源站| 51色欧美片视频在线观看| 在线看欧美日韩| 亚洲激情视频网站| 日韩av在线播放资源| 91精品国产91久久| 国产精品高潮粉嫩av| 精品久久久久久中文字幕| 亚洲网站在线观看| 91久久精品国产91久久性色| 亚洲国产精品va在看黑人| 国产精品一区二区三区免费视频| 精品日韩视频在线观看| 国产精品久久国产精品99gif| 亚洲国产成人精品女人久久久| 国产亚洲精品美女久久久| 国产精品高潮视频| 97精品伊人久久久大香线蕉| 欧美国产激情18| 亚洲影视九九影院在线观看| 国产91色在线播放| 免费不卡欧美自拍视频| 久久国内精品一国内精品| 日韩在线观看免费| 亚洲一区二区三区四区视频| 亚洲精品白浆高清久久久久久| 国内精久久久久久久久久人| 国产日本欧美一区二区三区| 成人黄色网免费| 尤物九九久久国产精品的特点| 国产一区二区三区中文| 日韩美女激情视频| 国产视频亚洲视频| 亚洲全黄一级网站| 久久久久久久久国产精品| 亚洲成成品网站| 91精品国产免费久久久久久| 成人高h视频在线| 国产一区二区三区欧美| 欧美日韩亚洲精品一区二区三区| 日韩欧美aⅴ综合网站发布| 亚洲欧美国产精品va在线观看| 有码中文亚洲精品| 欧美日韩国产成人在线| 亚洲综合日韩在线| 久久精品国产亚洲一区二区| 九九热视频这里只有精品| 日韩欧美成人精品| 国产亚洲欧美另类中文| 久久精品最新地址| 国产视频精品免费播放| 国产亚洲成精品久久| 亚洲第一网中文字幕| 91在线免费网站| 日韩成人av网| 国产精品成人一区二区| 97在线视频精品| 国产精品久久久久久搜索| 亚洲精品小视频在线观看| 高清一区二区三区四区五区| 91最新国产视频| 国产精品欧美久久久| 久久久免费在线观看| 日韩电影大片中文字幕| 国产精品91免费在线| 国产精品久久久久秋霞鲁丝| 精品日韩中文字幕| 久久成人在线视频| 亚洲iv一区二区三区| 九九热99久久久国产盗摄| 中国人与牲禽动交精品| 精品视频一区在线视频| 国产91色在线|| 欧美亚洲另类视频| 日韩人在线观看| 日韩国产在线看| 亚洲精品福利免费在线观看| 欧美亚洲免费电影| 91爱爱小视频k| 亚洲欧美精品伊人久久| 国产精品福利观看| 国产精品久久久一区| 欧美一级大胆视频| 久久香蕉精品香蕉| 亚洲第五色综合网| 欧美肥臀大乳一区二区免费视频| 26uuu另类亚洲欧美日本老年| 日韩欧美精品在线观看| 国产视频精品自拍| 日韩高清电影免费观看完整版| 91精品久久久久久久久不口人| 国产偷亚洲偷欧美偷精品| 亚洲第一男人av| 日本久久久久久久久| 国产欧美久久一区二区| 9.1国产丝袜在线观看| 成人字幕网zmw| 欧美大尺度电影在线观看| 这里只有精品丝袜| 国产日本欧美一区二区三区| 日韩欧美一区二区三区久久| 狠狠操狠狠色综合网| 国产精品自拍偷拍视频| 精品一区二区三区三区| 欧美电影在线观看网站| 欧美美女操人视频| 日韩不卡在线观看| 欧美大片免费观看在线观看网站推荐| 97视频在线看| 夜夜嗨av一区二区三区四区| 超碰精品一区二区三区乱码| 日韩国产欧美精品在线| 欧美丰满少妇xxxxx| 中文国产成人精品| 久久偷看各类女兵18女厕嘘嘘| 福利一区福利二区微拍刺激| 国内精品免费午夜毛片|