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
包含如下兩部分:架構
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之後開始支持xml
和javaConfig
的方式
@EnableAutoConfiguration
Spring3.1後引入Enable* , e.g. :
EnableScheduling
,EnableCache
EnableAsync
..
// 引入@Import({Registrar.class}) @AutoConfigurationPackage // 至關於xml: `<import resource ="***"/>`, `AutoConfigurationImportSelector`最終繼承於ImportSelector @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { // .... }
ImportSelector
、ImportBeanDefinitionRegistrar
// 方式① 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,\` // 略...
條件註冊:**
由於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 />