欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

SpringBoot自動(dòng)裝配原理詳解-創(chuàng)新互聯(lián)

目錄

我們注重客戶(hù)提出的每個(gè)要求,我們充分考慮每一個(gè)細(xì)節(jié),我們積極的做好成都網(wǎng)站建設(shè)、做網(wǎng)站服務(wù),我們努力開(kāi)拓更好的視野,通過(guò)不懈的努力,創(chuàng)新互聯(lián)贏得了業(yè)內(nèi)的良好聲譽(yù),這一切,也不斷的激勵(lì)著我們更好的服務(wù)客戶(hù)。 主要業(yè)務(wù):網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),微信小程序,網(wǎng)站開(kāi)發(fā),技術(shù)開(kāi)發(fā)實(shí)力,DIV+CSS,PHP及ASP,ASP.Net,SQL數(shù)據(jù)庫(kù)的技術(shù)開(kāi)發(fā)工程師。

1.環(huán)境和依賴(lài)

1.1.spring boot版本

1.2.依賴(lài)管理

2.自動(dòng)裝配

2.1.流程概述

2.2.三大步前的準(zhǔn)備工作

2.2.1.注解入口

2.2.2.獲取所有配置類(lèi)

2.3.獲取過(guò)濾列表

2.3.1.目的

2.3.2.過(guò)程

2.4.裝載

2.4.1.目的

2.4.2.過(guò)程

2.5.自動(dòng)配置

3.啟動(dòng)過(guò)程

3.1.整體流程

3.2.創(chuàng)建環(huán)境信息對(duì)象

3.3.創(chuàng)建應(yīng)用上下文對(duì)象

3.4.刷新應(yīng)用上下文對(duì)象

3.4.1.準(zhǔn)備刷新

3.4.2.刷新


1.環(huán)境和依賴(lài) 1.1.spring boot版本

springboot 2.2.X版本采用的maven構(gòu)建,2.3.X采用gradle構(gòu)建,因此采用2.2.X,mavan構(gòu)建的便于源碼閱讀。本文以2.2.9為例進(jìn)行Spring Boot自動(dòng)裝配原理的解析。

1.2.依賴(lài)管理

引入Spring Boot的方式有兩種

  • 引入spring-boot-dependencies的pom文件
  • 將spring-boot-starter-parent作為父級(jí)pom

這兩種方式的底層都是都是一樣的,都是引入了spring-boot-dependencies這個(gè)pom文件來(lái)管理Spring Boot的所有依賴(lài)。

SpringBoot中將一類(lèi)場(chǎng)景要用到的依賴(lài)封裝成一個(gè)starter,spring-boot-dependencies中包含了J2EE中所有場(chǎng)景(starter)的依賴(lài),并聲明了依賴(lài)的版本號(hào)。

2.自動(dòng)裝配 2.1.流程概述

首先所有JAVA程序的入口都是main方法,Spring Boot也不例外,只有main方法執(zhí)行時(shí),所有流程步驟才會(huì)執(zhí)行,此處我們只是從啟動(dòng)流程中剝離出和自動(dòng)裝配相關(guān)的流程來(lái)進(jìn)行單獨(dú)解析。只需要大致知道自動(dòng)裝配流程有幾步即可,如果有其它疑惑看后文的啟動(dòng)過(guò)程解析,就能豁然開(kāi)朗。

自動(dòng)裝配的整個(gè)流程可以分為三大步

  1. 獲取過(guò)濾列表
  2. 獲取自動(dòng)配置類(lèi)列表
  3. 比對(duì)移除、封裝返回

1.獲取條件列表

獲取類(lèi)自動(dòng)裝載的條件列表。

2.獲取自動(dòng)配置列表

獲取自動(dòng)裝載類(lèi)的列表。

3.比對(duì)移除、封裝返回

按照條件列表,將不滿(mǎn)足被自動(dòng)裝載條件的類(lèi)移除掉,返回滿(mǎn)足條件的類(lèi)列表。

2.2.三大步前的準(zhǔn)備工作 2.2.1.注解入口

@SpringBootApplication

該注解是個(gè)復(fù)合注解:

@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 {

@EnableAutoConfiguration啟動(dòng)自動(dòng)裝配:

@Import(AutoConfigurationImportSelector.class)? ,AutoConfigurationImportSelector會(huì)完成所有配置類(lèi)的獲取以及相關(guān)的準(zhǔn)備工作。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}
2.2.2.獲取所有配置類(lèi)

AutoConfigurationImportSelector被加載后,經(jīng)過(guò)層層調(diào)用,最終會(huì)調(diào)用到DeferredImportSelector中:

會(huì)去掃描所有@Configuration封裝成一個(gè)列表返回。

public IterablegetImports() {
            Iterator var1 = this.deferredImports.iterator();

            while(var1.hasNext()) {
                ConfigurationClassParser.DeferredImportSelectorHolder deferredImport = (ConfigurationClassParser.DeferredImportSelectorHolder)var1.next();
                this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector());
            }
			//將得到的自動(dòng)配置類(lèi)按照@order進(jìn)行排序
            return this.group.selectImports();
        }
2.3.獲取過(guò)濾列表 2.3.1.目的

獲取過(guò)濾列表,即去獲取META-INF/spring-autoconfigure-metadata.properties這一文件。這個(gè)文件中會(huì)詳細(xì)記錄Spring Boot自帶的各大J2EE場(chǎng)景的自動(dòng)配置類(lèi)(@Configuration)各自被自動(dòng)裝載生效的前提條件是什么。

2.3.2.過(guò)程

DeferredImportSelector.Group.process()中會(huì)首先獲取自動(dòng)裝配的過(guò)濾條件列表,該列表中記錄了待裝配的類(lèi)的裝配條件。獲取的核心方法是getAutoConfigurationMetadata(),該方法會(huì)根據(jù)傳過(guò)來(lái)的ClassLoader去遍歷加載classpath下的所有依賴(lài),獲取依賴(lài)中的META-INF/spring-autoconfigure-metadata.properties文件。

public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
			Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
					() ->String.format("Only %s implementations are supported, got %s",
							AutoConfigurationImportSelector.class.getSimpleName(),
							deferredImportSelector.getClass().getName()));
			//獲取自動(dòng)配置類(lèi)
			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
					.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
			this.autoConfigurationEntries.add(autoConfigurationEntry);
    		//解析存放自動(dòng)配置類(lèi)
			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
				this.entries.putIfAbsent(importClassName, annotationMetadata);
			}
		}

private AutoConfigurationMetadata getAutoConfigurationMetadata() {
			if (this.autoConfigurationMetadata == null) {
				this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
			}
			return this.autoConfigurationMetadata;
		}
final class AutoConfigurationMetadataLoader {

	protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";

	private AutoConfigurationMetadataLoader() {
	}

	static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
		return loadMetadata(classLoader, PATH);
	}

	static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
		try {
			Enumerationurls = (classLoader != null) ? classLoader.getResources(path)
					: ClassLoader.getSystemResources(path);
			Properties properties = new Properties();
			while (urls.hasMoreElements()) {
				properties.putAll(PropertiesLoaderUtils.loadProperties(new UrlResource(urls.nextElement())));
			}
			return loadMetadata(properties);
		}
		catch (IOException ex) {
			throw new IllegalArgumentException("Unable to load @ConditionalOnClass location [" + path + "]", ex);
		}
	}

過(guò)濾列表中會(huì)以KV鍵值對(duì)的方式記錄裝配條件,例如:

org.springframework.boot.autoconfigure.amqp.RabbitAnnotationDrivenConfiguration.ConditionalOnClass=org.springframework.amqp.rabbit.annotation.EnableRabbit

2.4.裝載 2.4.1.目的
  • 獲取自動(dòng)配置列表

  • 對(duì)比過(guò)濾列表,移除不滿(mǎn)足自動(dòng)裝載的類(lèi)

  • 封裝返回

2.4.2.過(guò)程

process()方法中會(huì)調(diào)用getAutoConfigurationEntry()方法,并將過(guò)濾列表傳和ClassLoader傳過(guò)去,在getCandidateConfigurations()方法中通過(guò)傳遞的ClassLoader獲取自動(dòng)裝配的列表"META-INF/spring.factories",然后比對(duì)過(guò)濾列表,將滿(mǎn)足條件的待裝配類(lèi)的全路徑記錄在AutoConfigurationImportSelector.AutoConfigurationGroup的一個(gè)叫autoConfigurationEntries的List中。

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   //從spring.factories中加載所有自動(dòng)配置類(lèi)
   Listconfigurations = getCandidateConfigurations(annotationMetadata, attributes);
   //移除重復(fù)配置類(lèi)
   configurations = removeDuplicates(configurations);
   //得到指定要移除的類(lèi)(@SpringBootApplication(exclude=FreeMarkerAutoConfiguration.class))
   Setexclusions = getExclusions(annotationMetadata, attributes);
   //檢查指定要移除的類(lèi),如果不是配置類(lèi),拋出異常
   checkExcludedClasses(configurations, exclusions);
   //移除指定要移除的自動(dòng)配置類(lèi)
   configurations.removeAll(exclusions);
   //獲取滿(mǎn)足條件的自動(dòng)配置類(lèi)列表
   configurations = filter(configurations, autoConfigurationMetadata);
   //記錄下符合條件的對(duì)象,并封裝在實(shí)體中返回
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}

一切執(zhí)行完畢后會(huì)回到入口出繼續(xù)向下執(zhí)行this.group.selectImports(),最終會(huì)調(diào)用到AutoConfigurationImportSelector的selectImports()方法,在該方法中會(huì)根據(jù)@order對(duì)自動(dòng)配置類(lèi)進(jìn)行排序。

public IterableselectImports() {
   if (this.autoConfigurationEntries.isEmpty()) {
      return Collections.emptyList();
   }
   SetallExclusions = this.autoConfigurationEntries.stream()
         .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
   SetprocessedConfigurations = this.autoConfigurationEntries.stream()
         .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
         .collect(Collectors.toCollection(LinkedHashSet::new));
   processedConfigurations.removeAll(allExclusions);

   return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
         .map((importClassName) ->new Entry(this.entries.get(importClassName), importClassName))
         .collect(Collectors.toList());
}
2.5.自動(dòng)配置

在自動(dòng)裝載步驟中已經(jīng)獲得需要加載的自動(dòng)配置類(lèi)的全路徑,接下來(lái)就是自動(dòng)配置。

以隨便一個(gè)AutoConfiguration類(lèi)為例:

頭上的一大串@Conditional注解其實(shí)就是過(guò)濾時(shí)的過(guò)濾條件,過(guò)濾列表其實(shí)就是通過(guò)這些條件注解生成的。

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
public class HttpEncodingAutoConfiguration {}

這個(gè)@Configuration滿(mǎn)足條件后其中的@Bean都會(huì)被自動(dòng)裝入IOC。

3.啟動(dòng)過(guò)程 3.1.整體流程

Spring boot的啟動(dòng)過(guò)程就是圍繞上下文的創(chuàng)建、準(zhǔn)備、刷新(填充)展開(kāi)的。

spring應(yīng)用上下文和servletContext不是一個(gè)東西,servlet上下文用來(lái)維系當(dāng)前應(yīng)用的一塊共享空間,目的是實(shí)現(xiàn)資源和數(shù)據(jù)在應(yīng)用中的全局共享。spring的上下文是一個(gè)維護(hù)Bean定義以及對(duì)象之間協(xié)作關(guān)系的高級(jí)接口,目的是維護(hù)好整個(gè)spring中的資源,如配置文件、Bean對(duì)象等,其涵蓋了IOC,但不只有IOC,可以理解為Spring應(yīng)用的一個(gè)抽象。

在SpringApplication的run()方法中創(chuàng)建應(yīng)用上下文,整個(gè)SpringApplication的run方法主要完成四個(gè)核心動(dòng)作:

  1. prepareEnvironment

    創(chuàng)建環(huán)境信息對(duì)象,解析環(huán)境參數(shù),包含配置文件、命令行傳參等。

  2. createApplicationContext

    創(chuàng)建應(yīng)用上下文對(duì)象

  3. prepareContext

    準(zhǔn)備應(yīng)用上下文對(duì)象

  4. refreshContext

    刷新應(yīng)用上下文對(duì)象

// 類(lèi) SpringApplication 代碼片段
	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		CollectionexceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
          // 包裝通過(guò)命令行傳入的名命令行參數(shù)
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
          // 結(jié)合命令行參數(shù) 準(zhǔn)備環(huán)境對(duì)象,該環(huán)境對(duì)象將會(huì)被設(shè)置到應(yīng)用上下文對(duì)象 ApplicationContext 上  ,
          // 環(huán)境對(duì)象通常包含如下信息 : 
          // 1. profile
          // 2. system properties
          // 3. system environment
          // 4. commandline arguments
          // 5. spring 配置文件
          // 6. 一個(gè)隨機(jī)值屬性源 random
          // 對(duì)于當(dāng)前 WebFlux 應(yīng)用來(lái)講,這里實(shí)現(xiàn)類(lèi)會(huì)使用 StandardReactiveWebEnvironment
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
          // 創(chuàng)建應(yīng)用上下文對(duì)象 ApplicationContext  
          // 實(shí)現(xiàn)類(lèi)會(huì)采用 : AnnotationConfigReactiveWebServerApplicationContext
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
          // 準(zhǔn)備應(yīng)用上下文對(duì)象 ApplicationContext          
          // 1. 關(guān)聯(lián)環(huán)境信息對(duì)象到應(yīng)用上下文對(duì)象
          // 2. 對(duì)象創(chuàng)建后置處理 : 設(shè)置容器的類(lèi)型轉(zhuǎn)換服務(wù)
          // 3. 初始化應(yīng)用上下文對(duì)象:調(diào)用各個(gè) ApplicationContextInitializer
          // 4. 廣播事件 : ApplicationContextInitializedEvent
          // 5. 將應(yīng)用程序參數(shù)作為一個(gè) bean 注冊(cè)到容器 : springApplicationArguments
          // 6. 將應(yīng)用程序入口類(lèi)作為 bean 注冊(cè)到容器 (load)
          // 7. 上下文加載完成生命周期事件回調(diào),為各個(gè)實(shí)現(xiàn)了 接口 ApplicationContextAware 的 
          //    ApplicationListener 設(shè)置應(yīng)用上下文對(duì)象屬性, 并廣播事件 : ApplicationPreparedEvent
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
          // 刷新應(yīng)用上下文對(duì)象  ApplicationContext 
          // 主要是調(diào)用應(yīng)用上下文對(duì)象  ApplicationContext  自身的 refresh 方法
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
            
          // 應(yīng)用程序上下文對(duì)象 ApplicationContext 已經(jīng)準(zhǔn)備就緒,
          // 現(xiàn)在調(diào)用各種開(kāi)發(fā)人員或者框架其他部分定義的 
          // ApplicationRunner 或者 CommandLineRunner
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}
3.2.創(chuàng)建環(huán)境信息對(duì)象
// SpringApplication 代碼片段
	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
       // 創(chuàng)建環(huán)境信息對(duì)象 environment
		ConfigurableEnvironment environment = getOrCreateEnvironment();
       // 將應(yīng)用程序參數(shù)關(guān)聯(lián)到環(huán)境信息對(duì)象 environment
		configureEnvironment(environment, applicationArguments.getSourceArgs());
       // 發(fā)布應(yīng)用程序事件 : 環(huán)境信息對(duì)象準(zhǔn)備好了 ,
       // 同步調(diào)用各個(gè)事件監(jiān)聽(tīng)器
		listeners.environmentPrepared(environment);
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}       
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

普通web應(yīng)用和reactive創(chuàng)建的環(huán)境信息對(duì)象類(lèi)型不同,但是實(shí)際功能相同,并沒(méi)有什么太大區(qū)別。

// SpringApplication 代碼片段
    private ConfigurableEnvironment getOrCreateEnvironment() {
		if (this.environment != null) {
			return this.environment;
		}
		switch (this.webApplicationType) {
		case SERVLET:
			return new StandardServletEnvironment();
		case REACTIVE:
			return new StandardReactiveWebEnvironment();
		default:
			return new StandardEnvironment();
		}
	}
3.3.創(chuàng)建應(yīng)用上下文對(duì)象

根據(jù)之前環(huán)境推斷中得到的當(dāng)前應(yīng)用的環(huán)境類(lèi)型來(lái)創(chuàng)建不同類(lèi)型的應(yīng)用上下文。

// SpringApplication 代碼片段
	protected ConfigurableApplicationContext createApplicationContext() {
		ClasscontextClass = this.applicationContextClass;
		if (contextClass == null) {
			try {
             // 根據(jù) this.webApplicationType 確定應(yīng)用上下文實(shí)現(xiàn)類(lèi)
				switch (this.webApplicationType) {
				case SERVLET:
            // DEFAULT_SERVLET_WEB_CONTEXT_CLASS 常量值為 : 
            // org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
            // 對(duì)應(yīng) Spring MVC Servlet Web 環(huán)境
					contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
					break;
				case REACTIVE:
            // DEFAULT_REACTIVE_WEB_CONTEXT_CLASS 常量值為 : 
            // org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext
            // 對(duì)應(yīng) Spring WebFlux Reactive Web 環(huán)境
					contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
					break;
				default:
            // DEFAULT_CONTEXT_CLASS 常量值為 : 
            // org.springframework.context.annotation.AnnotationConfigApplicationContext
            // 不對(duì)應(yīng)任何 Web 環(huán)境
					contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
				}
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
			"Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass",
			ex);
			}
		}
        
       // 確定應(yīng)用上下文實(shí)現(xiàn)類(lèi)之后,實(shí)例化應(yīng)用上下文對(duì)象 
		return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
	}
3.4.刷新應(yīng)用上下文對(duì)象 3.4.1.準(zhǔn)備刷新

這一步主要是完成刷新前的準(zhǔn)備工作,將除IOC相關(guān)的一切context中的東西全部賦值初始化好。

主要完成以下動(dòng)作:

  • 關(guān)聯(lián)環(huán)境信息

  • 查找調(diào)用各種前置、后置處理器(自定義的、自帶的)

  • 調(diào)用各種回調(diào)

  • 獲取主啟動(dòng)類(lèi)的路徑,將主啟動(dòng)類(lèi)封裝成一個(gè)BeanDefinition

// SpringApplication 代碼片段
	private void prepareContext(ConfigurableApplicationContext context, 
			ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, 
			ApplicationArguments applicationArguments, 
			Banner printedBanner) {
       // 1. 關(guān)聯(lián)環(huán)境信息對(duì)象到應(yīng)用上下文對(duì)象     
		context.setEnvironment(environment);
       // 2. 對(duì)象創(chuàng)建后置處理 : 設(shè)置容器的類(lèi)型轉(zhuǎn)換服務(wù) 
		postProcessApplicationContext(context);
       // 3. 初始化應(yīng)用上下文對(duì)象:調(diào)用各個(gè) ApplicationContextInitializer 
		applyInitializers(context);
       // 4. 廣播事件 : ApplicationContextInitializedEvent 
		listeners.contextPrepared(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
       // 5. 將應(yīng)用程序參數(shù)作為一個(gè) bean 注冊(cè)到容器 : springApplicationArguments 
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
		if (beanFactory instanceof DefaultListableBeanFactory) {
			((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
        
		// 獲取主啟動(dòng)類(lèi)的路徑
		Setsources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
       // 6. 將主啟動(dòng)類(lèi)封裝成一個(gè)BeanDefinition 
		load(context, sources.toArray(new Object[0]));
       // 7. 上下文加載完成生命周期事件回調(diào),為各個(gè)實(shí)現(xiàn)了 接口 ApplicationContextAware 的 
       //    ApplicationListener 設(shè)置應(yīng)用上下文對(duì)象屬性, 并廣播事件 : ApplicationPreparedEvent        
		listeners.contextLoaded(context);
	}3.4.2.刷新

主要是調(diào)用應(yīng)用上下文對(duì)象 ApplicationContext 自身的 refresh 方法,這是上下文對(duì)象的初始化中最關(guān)鍵的一步,該步驟中會(huì)完成幾個(gè)核心動(dòng)作:

  • 初始化IOC容器(即BeanFactory)

    該步驟中就會(huì)掃描解析注解,觸發(fā)自動(dòng)裝配.

  • 初始化WebServer容器

刷新應(yīng)用上下文的動(dòng)作其實(shí)是在spring相關(guān)的jar中,因此首先要有個(gè)概念,在這一步之前spring boot的動(dòng)作已經(jīng)完成,真正與IOC相關(guān)的動(dòng)作還是由spring來(lái)完成,所以說(shuō)spring boot是對(duì)spring的二次封裝。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 做一些初始化動(dòng)作
			prepareRefresh();
			// 獲取bean factory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// 初始化bean factory,為其成員屬性賦一些值
			prepareBeanFactory(beanFactory);
			try {
				// 獲取所有bean后置處理器
				postProcessBeanFactory(beanFactory);
				// **最核心的方法,注解的掃描,自動(dòng)配置類(lèi)的裝載,IOC的初始化等全在這個(gè)方法中
				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();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

初始化IOC:

創(chuàng)建容器其實(shí)沒(méi)有什么說(shuō)的,就是new一個(gè)web server(tomcat、netty或者jetty)出來(lái)。這里著重要說(shuō)一下初始化IOC。

入口在invokeBeanFactoryPostProcessors(beanFactory)。

IOC容器的初始化分為三步:

  • Resource定位

    定位到需要的各種路徑:

    • BasePackage

      這一步在準(zhǔn)備刷新的時(shí)候就已經(jīng)完成,并在封裝在了主啟動(dòng)類(lèi)封裝為的BeanDefinition中。

      基于BasePackage去掃描通過(guò)注解自定義的需要注入IOC的Bean。

    • 自動(dòng)配置類(lèi)的全路徑

      這一步在刷新應(yīng)用上下文的時(shí)候進(jìn)行,即去獲取factory.properties。

      基于自動(dòng)配置類(lèi)的全路徑去將對(duì)應(yīng)自動(dòng)配置類(lèi)注入IOC。

  • BeanDefinition載入

    將定位到的Resource記錄的Class分別封裝為一個(gè)個(gè)的Definition。

  • BeanDefinition注冊(cè)

    將Definition注冊(cè)進(jìn)IOC中。其實(shí)就是注入到一個(gè)ConcurrentHashMap中,IOC就是通過(guò)這個(gè)Map來(lái)持有這些BeanDefinition的。

IOC涉及的兩個(gè)核心概念:

  • BeanDefinition

  • BeanFactory

    IOC容器其實(shí)就是BeanFactory,BeanFactory就是IOC容器的規(guī)范接口,有多個(gè)實(shí)現(xiàn),最典型的就是DefalutListableBeanFactory,IOC容器中有一個(gè)成員Map(BeanDefinitionMap),該Map持有所有的BeanDefinition,用來(lái)維護(hù)Bean的基本信息(class、作用域等)

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

新聞名稱(chēng):SpringBoot自動(dòng)裝配原理詳解-創(chuàng)新互聯(lián)
分享路徑:http://www.chinadenli.net/article30/gsdpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)網(wǎng)站導(dǎo)航品牌網(wǎng)站制作網(wǎng)站維護(hù)動(dòng)態(tài)網(wǎng)站自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)