通過例項及原始碼分析關於SpringBoot啟動類啟動時自動配置問題
SpringBoot啟動類大家都不陌生,只要在main方法上增加一個@SpringBootApplication註解,就可以啟動了。
我們點開該註解
其中關鍵註解為@EnableAutoConfiguration,再次跟進
其中引入了EnableAutoConfigurationImportSelector.class,解釋見下圖
其中關鍵的方法為getCondidateConfiguration(metadata attributes)
中的SpringFactoriesLoader.loadFactoryNames(..)方法。
SpringFactoriesLoader預設查詢的位置就是”META-INF/spring.factories”,而在spring-boot-autoconfigure-1.4.7.jar中就有一個spring.factories。在其中配置了各種各樣的AutoConfigure類。到了這一步,我們算是找到了springBoot啟動時自動配置的源頭。就是在spring.factories中我們通過org.springframework.boot.autoconfigure.EnableAutoConfiguration配置的啟動時自動載入的自動配置類。所有的自動配置類採用了Spring4.0+的JAVA配置方法(即@
現在我們手寫一個自動配置包
1:首先我們建立一個SpringBoot的quickstart,然後在POM檔案中依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.3.4.RELEASE</version>
</dependency >
2:我們以如下圖路徑建立一個spring.factories的properties檔案。
建立好後。我們來建立一個自動配置類。為了節省空間,筆者這裡就不帶引入的包了。
通過引入了
@EnableConfigurationProperties(HelloServiceProperties.class)聲明瞭配置,就可以通過@Autowired將HelloServiceProperties的例項注入進來。
//這個註解代表這個類是個配置檔案
@Configuration
//這個註解代表會去自動載入HelloServiceProperties中的所有屬性
@EnableConfigurationProperties (HelloServiceProperties.class)
//這個註解代表會去import com.starrk.service.HelloService;這個路徑上尋找是否有類,如果有這個類,才進行載入bean
@ConditionalOnClass(HelloService.class)
//此註解會自動去application.properties中尋找prefix為hello,name/value(這兩個屬性是互斥的,name是value的別名)為starrk的
//當他的值為true時,載入當前類中的所有bean,當找不到時,設定為false,即不載入。
@ConditionalOnProperty(prefix = "hello",name = "starrk",havingValue = "true",matchIfMissing = false)
public class HelloServiceAutoConfigure {
@Autowired
private HelloServiceProperties helloServiceProperties;
@Bean
@ConditionalOnMissingBean(HelloService.class)//代表當沒有例項時,建立一個例項。
public HelloService helloService(){
HelloService helloService = new HelloService();
helloService.setMsg(helloServiceProperties.getMsg());
return helloService;
}
}
3:建立一個自動載入屬性的類來繫結你在application.properties中配置的屬性。
而HelloServiceProperties類上,如下圖所示進行了配置檔案繫結
@Data
@ConfigurationProperties(prefix = "hello")
public class HelloServiceProperties {
private static final String MSG = "may the force be with you";
private String msg =MSG;
}
這裡的@Data是使用了Lombok外掛,自動get/set,如果不使用可以手寫,都是一樣的。如果想使用可參考筆者文章
http://blog.csdn.net/weixin_39781526/article/details/78870944
@ConfigurationProperties是將HelloServiceProperties與你在Application.properties中的屬性進行了繫結,即如下圖
4:然後我們建立一個服務類HelloService
@Data
public class HelloService {
private String msg;
public String hello(){
return "hello, "+msg;
}
}
4:裝載我們的自動配置類在spring.factories中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.starrk.autoconfig.HelloServiceAutoConfigure
至此。自動配置包我們就建立完成。下面,我們來驗證一下是否成功
建立一個SpringBoot專案,然後依賴我們剛建立的包
<dependency>
<groupId>com.starrk</groupId>
<artifactId>autowired</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
建立啟動類
@RestController
@SpringBootApplication
public class Application {
@Autowired
private HelloService helloService;
@RequestMapping("/")
public String hello(){
return helloService.getMsg();
}
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
配置application.properties/yml設定啟動埠(可省略,隨意)
設定埠為9000
啟動當前的SpringBoot專案
得到結果
我們將自動配置包中的application.properties中的檔案裡的hello.msg註釋掉。
預期得到結果為may the force be with you
至此,自動配置的手寫及驗證完成。而這就是Spring自動配置的過程。