前言
在Spring階段,我們被各種XML文件配置或者配置類所困擾着,Spring有着“配置地獄”之稱
爲了簡化新 Spring 應用的初始搭建以及開發過程,提出了自動裝配的SpringBoot,
該框架遵循“約定優於配置”,使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置
約定優於配置
約定優於配置:按照約定的規範編程,而不是按照配置
以Spring+Mybatis爲例:
需要3個文件:Spring基本配置文件(設置自動掃描等)、mybatis配置文件(可以省略)、Spring+mybatis配置文件(bean裝配mybatis配置)
mybatis連接數據庫的配置必不可少:
<!--DataSource:使用Spring的數據源替換Mybatis的配置
使用spring提供的jdbc
-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--綁定Mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--綁定Mapper文件-->
<property name="mapperLocations" value="classpath:com/learn/dao/UserMapper.xml"/>
</bean>
<!--SqlSessionTemplate就是我們使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能構造器注入,沒有setter方法-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
而在SpringBoot+Mybatis:
一個application.yml配置文件即可
只需稍微配置:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
mybatis:
type-aliases-package: com.learn.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
爲什麼這麼簡單就配置好了?
因爲在SpringBoot中設置了默認約定,SpringBoot會自動裝配好我們需要的東西
如果需要自定義一些配置,在yml文件中配置,即開發人員僅需規定應用中不符合約定的部分,在沒有規定配置的地方,採用默認配置
SpringBoot中有哪些約定呢?
- Maven的目錄結構:src-main-resources,src-main-java,resources文件夾,存放資源配置文件,java文件夾存放java程序,必須要SpringbootApplication.java同層才能運行。默認的編譯生成的類都在targe文件夾下面
- springboot默認的配置文件必須是application.命名的yml文件或者properties文件(可以通過加上-後綴設置不同文件:application-dev.yml)
- application.yml中設置屬性需要按層次格式,Spring->datasource->url;mybatis->type-aliases-package等
@SpringBootApplication
SpringBoot有一個啓動類SpringbootApplication
package com.springbootweb;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Springbootweb01Application {
public static void main(String[] args) {
SpringApplication.run(Springbootweb01Application.class, args);
}
}
這是SpringBoot的入口,SpringBoot的啓動就是從該main方法啓動
它主要加載了@SpringBootApplication註解主配置類
來分析@SpringBootApplication註解
上面四個是元註解,下面的3個是我們需要關注的註解
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM,
classes = TypeExcludeFilter.class), @Filter(type =
FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@SpringBootConfiguration較簡單:
在Spring中就學了,@Configuration註解表示該類爲Spring的配置類
這個@SpringBootConfiguration註解功能一樣的
@EnableAutoConfiguration
EnableAutoConfiguration,直白的名字:開啓自動配置
分析:
該註解上有兩個重要的註解:
-
@AutoConfigurationPackage:添加該註解的類所在的package作爲自動配置package進行管理
-
@Import(AutoConfigurationImportSelector.class):導入了一個
AutoConfigurationImportSelector選擇器給Spring容器中來導入一些組件
@AutoConfigurationPackage註解:導入AutoConfigurationPackages.Registrar註冊器
{ @link ImportBeanDefinitionRegistrar } to store the base package from the importing configuration.
就不深入解析了,該註解大致的意思就是:當SpringBoot應用啓動時默認會將啓動類所在的package作爲自動配置的package,所以說我們的包應當和SpringBootApplication類同層
@Import(AutoConfigurationImportSelector.class)
版本爲2.2.6 RELEASE,不同的版本有一定的更改
父類裏面規定了一個方法叫selectImports方法,查看了selectImports這個方法裏面的代碼內容就能知道導入了哪些組件:
調用了getAutoConfigurationEntry方法,顧名思義:獲得自動裝配組件
該方法會返回configurations,這個就是配置對象集合
通過getCandidateConfigurations方法獲得,獲得候選配置
SpringFactoriesLoader.loadFactoryNames
是這裏關鍵的方法,Spring工廠加載類
該方法會掃描具有META-INF/spring.factories文件的jar包,把這個文件的urls拿到之後並把這些urls遍歷,最終把這些文件整成一個properties對象
然後它從properties對象裏邊獲取一些值,把這些獲取到的值來加載我們最終要返回的這個結果result,result就是我們要交給Spring容器中的所有組件
factoryTypeName就是我們傳過來的Class的這個類名。
是前面SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())
,傳入的getSpringFactoriesLoaderFactoryClass()方法中得到,從properties中獲取到EnableAutoConfiguration.class類名:
SpringFactoriesLoader會根據這個EnableAutoConfiguration.class去spring.factories找EnableAutoConfiguration.class所對應的values,並返回
spring.factories
META-INF/spring.factories
文件在Spring-boot-autuoconfigure包下
這個配置文件配置了很多自動裝配的信息:
這些自動裝配類xxxAutoConfiguration都是SpringBoot自動裝配的相關類,是SpringBoot自動裝配的核心
每個xxxAutoConfiguation類都定義了相關bean的實例化配置,說明了哪些bean可以被自動配置,什麼條件下可以自動配置,並把這些bean實例化出來
我們打開一個常見的DataSourceAutoConfiguration,進入查看
- @Configuration(proxyBeanMethods = false):表明這是一個配置類,
proxyBeanMethods = false
表示該類不會被代理,提供性能 - @ConditionalOnClass:當SpringIoC容器內存在指定Class的條件,表示對應的jar包是否導入了,這類註解用來判斷是否執行自動裝配
- @EnableConfigurationProperties(DataSourceProperties.class):導入對應的啓動裝配屬性類:DataSourceProperties
- @Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceInitializationConfiguration.class }):相關的配置類
主要就是DataSourceProperties,這個類中定義自動裝配的配置:
表示配置前綴是:spring.datasource
內部屬性有:
這些就是在application.yml文件中自定義配置的屬性:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
到這,應該明白了 spring.factories的作用:
- 在該文件中配置好SpringBoot需要的自動配置類,當啓動SpringBoot時會加載該文件,並一個個加載這些xxxAutoConfiguration類
- 而在這些類中,會有一類ConditionalOnXxx註解判斷該類是否自動裝配
- 如果是自動裝配,會加載EnableConfigurationProperties註解導入的Properties類,該類中會有成員變量,這些變量對應着yml文件可以設置的字段
總結
我們可以大致總結自動配置:
-
SpringBootApplication啓動類,是SpringBoot程序的入口,關鍵在與@SpringBootApplication註解
-
該註解有兩個重要的元註解:@SpringBootConfiguration表示該類爲Spring的配置類;@EnableAutoConfiguration
-
@EnableAutoConfiguration有兩個重要元註解:
@AutoConfigurationPackage表示當SpringBoot應用啓動時默認會將啓動類所在的package作爲自動配置的package
@Import(AutoConfigurationImportSelector.class)導入了一個選擇器 -
AutoConfigurationImportSelector的selectImports方法決定SpringBoot導入的組件,經過一系列的方法調用最終會使用SpringFactoriesLoader加載器負責加載配置類名,loadSpringFactories方法讀取自動配置工程的META-INF/spring.factories配置文件,加載配置類的全類名,包裝成Properties對象,返回result就是交給Spring容器的組件
-
spring.factories內部編寫好了全部的自動裝配類,啓動SpringBoot時,會加載這些自動裝配類xxxAutoConfiguration,這些自動裝配類有元註解ConditionalOnXxx判斷是否自動裝配,如果判斷確定自動裝配,會加載相關的Properties屬性類,該屬性類屬性字段對應yml文件中的字段
學海無涯苦作舟