SpringBoot中的starter是一種非常重要的機制,能夠拋棄以前繁雜的配置,將其統一集成進starter,應用者只需要在maven中引入starter依賴,SpringBoot就能自動掃描到要加載的信息並啓動相應的默認配置。starter讓我們擺脫了各種依賴庫的處理,需要配置各種信息的困擾。SpringBoot會自動通過classpath路徑下的類發現需要的Bean,並註冊進IOC容器。SpringBoot提供了針對日常企業應用研發各種場景的spring-boot-starter依賴模塊。所有這些依賴模塊都遵循着約定成俗的默認配置,並允許我們調整這些配置,即遵循“約定大於配置”的理念。
在我們的日常開發工作中,經常會有一些獨立於業務之外的配置模塊,我們經常將其放到一個特定的包下,然後如果另一個工程需要複用這塊功能的時候,需要將代碼硬拷貝到另一個工程,重新集成一遍,麻煩至極。如果我們將這些可獨立於業務代碼之外的功配置模塊封裝成一個個starter,複用的時候只需要將其在pom中引用依賴即可,SpringBoot爲我們完成自動裝配.
首先是官方給定的自定義starter命名規則:
SpringBoot提供的starter以spring-boot-starter-xxx
的方式命名的。官方建議自定義的starter使用xxx-spring-boot-starter
命名規則。以區分SpringBoot生態提供的starter。
下面開始代碼:
新建一個工程:
依賴如下:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wm</groupId>
<artifactId>my-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>my-spring-boot-starter</name>
<description>自定義spring boot start,集成web,lombok</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>
定義讀取自定義配置屬性的類:
package com.wm.myspringbootstarter.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/***
* @ClassName: MyPropertiesConfig
* @Description: 讀取配置類屬性
* @Author: wm_yu
* @Create_time: 13:57 2020-1-15
*/
@ConfigurationProperties(prefix = "start")
@Data
@Component
public class MyPropertiesConfig {
/**
* 禁用標識
*/
private Boolean enable;
/**
* 內容
*/
private String content;
/**
* 誰說的
*/
private String who;
}
定義一個service,給定方法:
package com.wm.myspringbootstarter.service;
import lombok.AllArgsConstructor;
import lombok.Data;
/***
* @ClassName: TestService
* @Description: 定義一個service
* @Author: wm_yu
* @Create_time: 14:03 2020-1-15
*/
@Data
@AllArgsConstructor
public class TestService {
private String who;
private String content;
public String doSth(){
return String.format("%s say this content is: %s",who,content);
}
}
定義配置類:
package com.wm.myspringbootstarter.config;
import com.wm.myspringbootstarter.service.TestService;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
* @ClassName: MyConfig
* @Description:
* @Author: wm_yu
* @Create_time: 14:06 2020-1-15
*/
@Configuration
//只有配置的start.enable爲true,這個配置屬性類才加載生效
@ConditionalOnExpression("${start.enable:true}")
@AllArgsConstructor
public class MyConfig {
private final MyPropertiesConfig myPropertiesConfig;
@Bean
public TestService testService(){
return new TestService(myPropertiesConfig.getWho(),myPropertiesConfig.getContent());
}
}
下面是定義factories文件:
#-------starter自動裝配---------
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wm.myspringbootstarter.config.MyConfig
好了,上面是定義的starter代碼,我們將其install到本地倉庫
在新建一個項目,應用這個starter:
依賴如下:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.wm</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--引入自定義的start依賴-->
<dependency>
<groupId>com.wm</groupId>
<artifactId>my-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
定義cotroller測試類:
package com.wm.demo.controller;
import com.wm.myspringbootstarter.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* @ClassName: TestController
* @Description:
* @Author: wm_yu
* @Create_time: 14:21 2020-1-15
*/
@RestController
@Slf4j
public class TestController {
@Autowired(required = false)
private TestService testService;
@GetMapping("/test")
public String doSth(){
log.info("開始測試.....");
if(ObjectUtils.isEmpty(testService)){
log.info("配置文件中設置爲不加載config.....");
return null;
}
String s = testService.doSth();
log.info("調用後的返回值:[{}]",s);
return s;
}
}
在啓動類中,掃描當前包及其自定義的starter下的子包:
package com.wm.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.wm")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
假設我們的application.yml沒有任何的配置,啓動訪問:
就是enable爲空,也會加載我們的配置類:
下面給定enable爲false的情況:
可以看到沒有加載配置類的生成
在給定enable爲true的情況:
下面說明下@ConditionalOnExpression的使用: