在咱們學習SpringBoot
時都已經瞭解到starter
是SpringBoot
的核心組成部分,SpringBoot
爲咱們提供了儘量完善的封裝,提供了一系列的自動化配置的starter
插件,咱們在使用spring-boot-starter-web
時只須要在pom.xml
配置文件內添加依賴就能夠了,咱們以前傳統方式則是須要添加不少相關SpringMVC
配置文件。而spring-boot-starter-web
爲咱們提供了幾乎全部的默認配置,很好的下降了使用框架時的複雜度。
所以在使用xx.starter
時你就不用考慮該怎麼配置,即使是有一些必要的配置在application.properties
配置文件內對應配置就能夠了,那好,爲何我在application.properties
配置對應屬性後xx.starter
就能夠獲取到並做出處理呢?下面咱們帶着這個疑問來編寫咱們自定義的starter
讓咱們深刻了解SpringBoot
java
自定義starter
而且經過spring-boot-autoconfigure
完成自動化配置。git
建立starter
項目咱們並不須要建立SpringBoot
項目,咱們建立一個Maven
項目就能夠知足咱們的需求,建立項目完成後pom.xml
配置信息以下所示:web
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yuqiyu</groupId>
<artifactId>chapter28</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
</dependencies>
</project>複製代碼
咱們這個starter
並不作其餘複雜邏輯的編寫,因此這裏的依賴只是添加了spring-boot-autoconfigure
,實戰開發時能夠添加任意依賴到項目中。spring
咱們在文章開頭埋下了一個疑問,starter
是如何讀取application.properties
或者application.yml
配置文件內須要的配置參數的呢?那麼接下來咱們就看看如何能夠獲取自定義的配置信息。SpringBoot
在處理這種事情上早就已經考慮到了,因此提供了一個註解@ConfigurationProperties
,該註解能夠完成將application.properties
配置文件內的有規則的配置參數映射到實體內的field
內,不過須要提供setter方法,自定義配置參數實體代碼以下所示:apache
package com.yuqiyu.chapter28;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 配置文件實體映射
* ========================
* Created with IntelliJ IDEA.
* User:恆宇少年
* Date:2017/7/22
* Time:22:51
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@ConfigurationProperties(prefix = "hello")
public class HelloProperties
{
//消息內容
private String msg = "HengYu";
//是否顯示消息內容
private boolean show = true;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public boolean isShow() {
return show;
}
public void setShow(boolean show) {
this.show = show;
}
}複製代碼
在上面代碼中,@ConfigurationProperties
註解內咱們使用到了屬性preffix
,該屬性配置了讀取參數的前綴,根據上面的實體屬性對應配置文件內的配置則是hello.msg
、hello.show
,固然咱們提供了默認值,配置文件內不進行配置時則是使用默認值。springboot
咱們爲自定義starter
提供一個Service
,而且提供一個名爲sayHello
的方法用於返回咱們配置的msg
內容。代碼以下所示:bash
package com.yuqiyu.chapter28;
/**
* 自定義業務實現
* ========================
* Created with IntelliJ IDEA.
* User:恆宇少年
* Date:2017/7/22
* Time:22:54
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
public class HelloService
{
//消息內容
private String msg;
//是否顯示消息內容
private boolean show = true;
public String sayHello()
{
return show ? "Hello," + msg : "Hidden";
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setShow(boolean show) {
this.show = show;
}
}複製代碼
咱們Service
內的代碼比較簡單,根據屬性參數進行返回格式化後的字符串。app
接下來咱們開始編寫自動配置,這一塊是starter
的核心部分,配置該部分後在啓動項目時纔會自動加載配置,固然其中有不少細節性質的配置框架
自動化配置其實只是提供實體bean的驗證以及初始化,咱們先來看看代碼:maven
package com.yuqiyu.chapter28;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 自定義starter自動化配置
* ========================
* Created with IntelliJ IDEA.
* User:恆宇少年
* Date:2017/7/22
* Time:22:56
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@Configuration//開啓配置
@EnableConfigurationProperties(HelloProperties.class)//開啓使用映射實體對象
@ConditionalOnClass(HelloService.class)//存在HelloService時初始化該配置類
@ConditionalOnProperty//存在對應配置信息時初始化該配置類
(
prefix = "hello",//存在配置前綴hello
value = "enabled",//開啓
matchIfMissing = true//缺失檢查
)
public class HelloAutoConfiguration
{
//application.properties配置文件映射前綴實體對象
@Autowired
private HelloProperties helloProperties;
/**
* 根據條件判斷不存在HelloService時初始化新bean到SpringIoc
* @return
*/
@Bean//建立HelloService實體bean
@ConditionalOnMissingBean(HelloService.class)//缺失HelloService實體bean時,初始化HelloService並添加到SpringIoc
public HelloService helloService()
{
System.out.println(">>>The HelloService Not Found,Execute Create New Bean.");
HelloService helloService = new HelloService();
helloService.setMsg(helloProperties.getMsg());//設置消息內容
helloService.setShow(helloProperties.isShow());//設置是否顯示
return helloService;
}
}複製代碼
自動化配置代碼中有不少咱們以前沒有用到的註解配置,咱們從上開始講解
@Configuration
:這個配置就不用多作解釋了,咱們一直在使用@EnableConfigurationProperties
:這是一個開啓使用配置參數的註解,value
值就是咱們配置實體參數映射的ClassType
,將配置實體做爲配置來源。
有關@ConditionalOnXxx
相關的註解這裏要系統的說下,由於這個是咱們配置的關鍵,根據名稱咱們能夠理解爲具備Xxx條件
,固然它實際的意義也是如此,條件註解是一個系列,下面咱們詳細作出解釋
@ConditionalOnBean
:當SpringIoc
容器內存在指定Bean
的條件@ConditionalOnClass
:當SpringIoc
容器內存在指定Class
的條件@ConditionalOnExpression
:基於SpEL表達式做爲判斷條件@ConditionalOnJava
:基於JVM
版本做爲判斷條件@ConditionalOnJndi
:在JNDI存在時查找指定的位置@ConditionalOnMissingBean
:當SpringIoc
容器內不存在指定Bean
的條件@ConditionalOnMissingClass
:當SpringIoc
容器內不存在指定Class
的條件@ConditionalOnNotWebApplication
:當前項目不是Web項目的條件@ConditionalOnProperty
:指定的屬性是否有指定的值@ConditionalOnResource
:類路徑是否有指定的值@ConditionalOnSingleCandidate
:當指定Bean
在SpringIoc
容器內只有一個,或者雖然有多個可是指定首選的Bean
@ConditionalOnWebApplication
:當前項目是Web項目的條件
以上註解都是元註解@Conditional
演變而來的,根據不用的條件對應建立以上的具體條件註解。
到目前爲止咱們尚未完成自動化配置starter
,咱們須要瞭解SpringBoot
運做原理後才能夠完成後續編碼。
在註解@SpringBootApplication
上存在一個開啓自動化配置的註解@EnableAutoConfiguration
來完成自動化配置,註解源碼以下所示:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}複製代碼
在@EnableAutoConfiguration
註解內使用到了@import
註解來完成導入配置的功能,而EnableAutoConfigurationImportSelector
內部則是使用了SpringFactoriesLoader.loadFactoryNames
方法進行掃描具備META-INF/spring.factories
文件的jar包。咱們能夠先來看下spring-boot-autoconfigure
包內的spring.factories
文件內容,以下所示:
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer
# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnClassCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
.....省略複製代碼
能夠看到配置的結構形式是Key
=>Value
形式,多個Value
時使用,
隔開,那咱們在自定義starter
內也可使用這種形式來完成,咱們的目的是爲了完成自動化配置,因此咱們這裏Key
則是須要使用org.springframework.boot.autoconfigure.EnableAutoConfiguration
咱們在src/main/resource
目錄下建立META-INF
目錄,並在目錄內添加文件spring.factories
,具體內容以下所示:
#配置自定義Starter的自動化配置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.yuqiyu.chapter28.HelloAutoConfiguration複製代碼
都目前爲止咱們的自定義starter
已經配置完成,下面咱們須要新建一個SpringBoot
項目來測試咱們的自動化配置是否已經生效。
在使用自定義starter
以前須要將starter
做Maven Jar Install
到本地,咱們使用idea工具自帶的maven命令完成該操做
步驟:工具右側 -> Maven Projects -> Lifecycle -> install
建立測試項目的pom.xml
配置文件內容以下所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yuqiyu.sample</groupId>
<artifactId>test-spring-boot-starter-hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test-spring-boot-starter-hello</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--自定義starter依賴-->
<dependency>
<groupId>com.yuqiyu</groupId>
<artifactId>chapter28</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>複製代碼
咱們只須要將依賴添加到pom.xml
配置文件內
在運行項目以前,咱們打開application.properties
配置文件開啓debug
模式,查看自動化配置的輸出日誌,配置內容以下所示:
#顯示debug日誌信息
debug=true複製代碼
接下來咱們啓動項目,在控制檯查找是否存在咱們的HelloAutoConfiguration
日誌輸出,控制檯輸出內容以下所示:
.....省略
>>>The HelloService Not Found,Execute Create New Bean.
.....省略
HelloAutoConfiguration matched:
- @ConditionalOnClass found required class 'com.yuqiyu.chapter28.HelloService'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
- @ConditionalOnProperty (hello.enabled) matched (OnPropertyCondition)
HelloAutoConfiguration#helloService matched:
- @ConditionalOnMissingBean (types: com.yuqiyu.chapter28.HelloService; SearchStrategy: all) did not find any beans (OnBeanCondition)
.....省略複製代碼
在控制檯能夠看到咱們的自定義starter
的自動化配置已經生效了,而且根據@ConditionalOnMissingBean(HelloService.class)
作出了條件注入HelloService
實體bean到SpringIoc
容器內
咱們來編寫一個簡單的測試控制器,查看HelloService
在不配置參數狀況下輸出格式化字符串內容,控制器代碼以下所示:
package com.yuqiyu.sample.testspringbootstarterhello;
import com.yuqiyu.chapter28.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 測試自定義starter自動化配置HelloService
* ========================
* Created with IntelliJ IDEA.
* User:恆宇少年
* Date:2017/7/23
* Time:11:42
* 碼雲:http://git.oschina.net/jnyqy
* ========================
*/
@RestController
public class HelloController
{
//注入自定義starter內邏輯
@Autowired
HelloService helloService;
/**
* 測試訪問地址/hello
* @return 格式化字符串
*/
@RequestMapping(value = "/hello")
public String sayHello()
{
return helloService.sayHello();
}
}複製代碼
接下來咱們重啓下項目,訪問地址http://127.0.0.1:8080/hello,界面輸出內容以下所示:
Hello,HengYu複製代碼
界面輸出的內容是咱們默認值,接下來咱們在application.properties
配置文件內對應添加hello.msg
、hello.show
配置參數,以下所示:
#配置自定義starter參數
hello.msg=HengYu Boy
hello.show=true複製代碼
重啓項目,再次訪問地址,界面輸出內容以下所示:
Hello,HengYu Boy複製代碼
咱們的配置生效了,到目前爲止我相信你們已經明白了咱們application.properties
配置文件爲何能夠做爲統一配置入口,爲何配置後能夠被對應starter
所使用。
以上內容是本章的所有講解,本章主要講解了咱們如何自定義starter
而且自動化配置到SpringBoot
項目中,固然裏面還有不少神奇的地方須要你們去深刻挖掘。
本章代碼已經上傳到碼雲:
SpringBoot配套源碼地址:gitee.com/hengboy/spr…
SpringCloud配套源碼地址:gitee.com/hengboy/spr…
SpringBoot相關係列文章請訪問:目錄:SpringBoot學習目錄
QueryDSL相關係列文章請訪問:QueryDSL通用查詢框架學習目錄
SpringDataJPA相關係列文章請訪問:目錄:SpringDataJPA學習目錄
感謝閱讀!
歡迎加入QQ技術交流羣,共同進步。