SpringBoot開篇

SpringBootjava

前言:

SpringBoot是一個服務於Spring框架的框架,用來簡化對於bean的獲取, 快速構建一個web服務, 它的基礎依然是Spring。web

在SpringBoot還未出來之前使用的最多的架構體系多是SpringMVC + Mybatis or Spring + Struts2 +Hibernate ,甚至是最先期的JSP + Servlet. 以上框架搭建起來過於繁瑣,並且須要進行大量的配置,每次搭建一個web項目可能會遇到各類各樣的問題,因此通常公司都會生成相應的腳手架,以便於可以提高開發效率。spring

隨着互聯網的發展,最開始的單體架構可能難以支撐大流量的場景, 那麼架構演進的一個必然的結果是須要對於系統架構拆分,由最開始的單體架構拆分紅N個業務系統,那麼服務與服務之間的調用就須要提供相應的通訊方式與協議等,例如HTTP 或者RPC(dubbo的底層通訊方式是經過Netty實現,即暴露服務的端口供遠程調用)的方式進行調用。api

1.什麼是SpringBoottomcat

1.1. Spring基礎,IOC 控制反轉springboot

包含如下兩部分:架構

  • DI 依賴注入
  • DL 依賴查找

1.2. SpringBoot實現快速開發的基礎來源於 約定優於配置框架

什麼是約定優於配置:例如A和B兩我的剛認識,爲了昇華一下雙方的友誼,因而約定某天某一時刻在某地喝茶, 那麼第二次可能只須要說老地方見就知道該去哪裏,那麼到了後來可能只須要一個眼神交流便可。maven

1.2.1 約定優於配置的體現ide

  • maven的目錄結構(默認以jar的形式打包,默認會有resources目錄)
  • springboot-starter-xxx的方式, e.g. springboot-starter(內置了tomcat, resource/{template,static} )

1.2.2. 爲何說SpringBoot裏沒有新技術

1.2.2.1. 自動裝配

@SpringBootApplication 是由如下三個註解組成的

  • @SpringBootConfiguration

@Configuration 註解標註。 --> 本質上仍是由@Component標註。 Spring最開始採用XML的方式 e.g. : <bean id="xxx" class ="com.xxxx.A"/>

Spring3開始支持 javaConfig的方式(始於JDK5), Spring3之後開始支持xmljavaConfig的方式

  • @EnableAutoConfiguration

Spring3.1後引入Enable* , e.g. : EnableScheduling, EnableCache EnableAsync ..

// 引入@Import({Registrar.class})
@AutoConfigurationPackage
// 至關於xml: `<import resource ="***"/>`, `AutoConfigurationImportSelector`最終繼承於ImportSelector 
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
	// ....
}

實現動態注入的方式:

ImportSelectorImportBeanDefinitionRegistrar

// 方式①
public class CachedRegister implements ImportBeanDefinitionRegistrar {
  @Override
  public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
      RootBeanDefinition beanDefinition = new RootBeanDefinition(DiskPersistent.class);
      String beanName = StringUtils.uncapitalize(DiskPersistent.class.getName());
      // beanName相當於<bean name ="beanName"></bean>
      beanDefinitionRegistry.registerBeanDefinition(beanName, beanDefinition);
  }
// 方式②	
public class ProviderSelector implements ImportSelector {
  @Override
  public String[] selectImports(AnnotationMetadata annotationMetadata) {
      return new String[]{CachedService.class.getName(),HealthManagerService.class.getName()};
  }
}
// 控制檯打印,能夠獲取到以下內容,這只是個簡單的演示,能夠在這裏作一些其餘的事情(加深本身的印象)
//HealthManagerService@57a4d5ee
//DiskPersistent@5af5def9

AutoConfiguration (自動注入, 簡化Bean的注入)

@EnableAutoConfiguration中導入了AutoConfigurationImportSelector 經過ImportSelector不難知道其中一定會有selectImports方法,

public String[] selectImports(AnnotationMetadata annotationMetadata) {
     if (!this.isEnabled(annotationMetadata)) {
         return NO_IMPORTS;
     } else {
			// 這裏在加載META-INF/spring-autoconfigure-metadata.properties文件 
         AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
			//看這裏
         AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
         return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
     }
 }

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, 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);
			//過濾註解屬性exlude={}
         Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
         this.checkExcludedClasses(configurations, exclusions);
         configurations.removeAll(exclusions);
         configurations = this.filter(configurations, autoConfigurationMetadata);
         this.fireAutoConfigurationImportEvents(configurations, exclusions);
         return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
     }
 }

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
	    // `SpringFactoriesLoader` (`spring SPI機制`),這裏會加載全部的 `META-INF/spring.factories`文件裏的數據
     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;
 }

spi(service provider interface) 是什麼? --> 提供擴展點供開發人員使用 e.g. java ,spring,dubbo都提供了相應的spi

在META-INF下建立: spring.factories 添加本身的類便可加載: e.g.: org.springframework.boot.autoconfigure.EnableAutoConfiguration= xxx.xxx.A

以下是spring自帶的的:

# `AutoConfiguration`
  `org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.springframework.cloud.client.CommonsClientAutoConfiguration,\
  org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\`
  // 略...

條件註冊:**

NOTE:

由於SpringBoot會考慮到各類各樣的場景,因此須要加載的資源會比較多,而有些時候大部分場景咱們壓根使用不到,因此能夠經過條件註解

使用方式:

ConditionalOnXXX
e.g. ConditionalOnClass = "com.xxx.A"META-INF下添加 spring-autoconfigure-metadata.properties

com.a.AConfig.ConditionalOnClass  = com.xxx.A
  
  // spring中的
  org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration.ConditionalOnClass=org.influxdb.InfluxDB
  @AutoConfigurationPackage
  @Import({AutoConfigurationImportSelector.class})
  • @ComponentScan

掃描 @Component, @Service, @Controller, @Configuration 等(註解具備派生性,@Component及派生註解都將被掃描) 而後被IOC託管。
等價於 : Spring XML的方式<context-componet-scan />

相關文章
相關標籤/搜索