Springboot系列-自定義starter
前言:用過springboot的各位應該都知道,Springboot相對於Spring/SpringMVC要方便的多,爲什麼呢?這主要還是歸功於Starter,其實Starter也是基於Spring/SpringMVC基礎上實現的,因爲Starter帶來了許多的自動化配置,所以在我們開發的時候省了不少力
理解Starter
那麼Starter是基於什麼才能夠實現衆多自動化配置的呢?其實Starter的核心註解就是@Conditional,當classpath下面存在某一個class時,這個配置纔會生效
自定義Starter
定義Starter
1.首先創建一個普通的新的maven項目,創建完成之後添加Starter的自動化配置類如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
配置完之後其實我們可以通過源碼看到,好多自動化配置已經引入進來了
2.配置完成之後創建一個DemoProperties類,用來接收application.properties中注入的值,如下:
@ConfigurationProperties(prefix = "test")
public class DemoProperties {
private String name = "王先森";
private String hobby = "Coding";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
以上這個DemoProperties配置類的意思就是直接將application.properties裏面的屬性值注入到該實例中,@ConfigurationProperties 類型安全的屬性注入,即將 application.properties 文件中前綴爲 javaboy 的屬性注入到這個類對應的屬性上
application.prpoerties配置文件內容如下:
test.name = wxy
test.hobby = basketball
3.配置完DemoProperties之後,在定義一個DemoService類並定義個方法如下:
public class DemoService {
private String name;
private String hobby;
public String doSomething() {
return name + " do " + hobby + " !";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHobby() {
return hobby;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
}
上面這個DemoService意思就是很簡單的一個類,添加了個doSomething方法,之後再對應文件將該類注入之後,傳入屬性值調用該方法
4.接下來要做的是非常關鍵,就是關於自動配置的定義,因爲之前我們可能用的都是別人定義的,所以這次需要自己去定義
@Configuration
@EnableConfigurationProperties(DemoProperties.class)
@ConditionalOnClass(DemoService.class)
public class DemoServiceAutoConfiguration {
@Autowired
DemoProperties demoProperties;
@Bean
DemoService demoService(){
DemoService demoService = new DemoService();
demoService.setName(demoProperties.getName());
demoService.setHobby(demoProperties.getHobby());
return demoService;
}
}
針對以上一段自動配置,解釋如下:
- Configuration:表示這是一個配置類
- EnableConfigurationProperties:此註解是爲了使之前配置的@ConfigurationProperties 生效
- @ConditionalOnClass :表示項目當前classpath下存在DemoService時,後面的配置纔會生效
- 自動配置類中首先注入 DemoProperties ,該實例中有在 application.properties 中配置的相關數據
- 提供一個 DemoService 的實例,將 DemoProperties 中的值注入進去
5.自動化配置類基本完成,接下來還需要一個 spring.factories 文件,那麼這個文件是幹什麼用的呢?我們知道Springboot項目中有一個啓動類,該啓動類包含了@SpringBootApplication 註解,這個註解的定義如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
根據上面我們可以看出其實SpringBootApplication 是一個組合註解,它包含了如上註解,其最重要和關鍵的三個註解並解釋如下:
- @SpringBootConfiguration:此註解爲Springboot配置註解,如下又在該註解中又包含如下註解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
- @EnableAutoConfiguration:開啓自動配置註解,只有開啓了這個自動配置之後自動配置纔會生效,其註解又包含如下註解:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
- @ComponentScan:這個註解在有一個主要的功能就是配置註解掃描,可以自定義去配置掃描的範圍
6.在 Maven 項目的 resources 目錄下創建一個名爲 META-INF 的文件夾,然後在文件夾中創建一個名爲 spring.factories 的文件,文件內容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wxy.entity.DemoServiceAutoConfiguration
動化配置類的路徑配置完成,如此之後我們的自動化配置類就算完成了
本地安裝
我們將我們寫好的Starter項目進行打包,如下:
雙擊完成後,這個 Starter 就安裝到我們本地倉庫了,其實這個時候我們從該路徑可以發現他打包成了一個jar包,如下:
那麼如何使用它呢?
使用Starter
新建一個普通的 Spring Boot 工程,創建成功之後,加入自定義 Starter 的依賴,如下:
<dependency>
<groupId>com.example</groupId>
<artifactId>emptyMavenProject</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
此時我們引入了上面自定義的 Starter ,也就是說項目中現在有一個默認的 DemoService 實例可以使用,關於此實例的數據,可以在 application.properties 中進行配置,如下:
test.name = Wang sir
test.hobby = Coding
配置完成後,可選擇在單元測試方法中注入 DemoSerivce 實例來使用,代碼如下:
@SpringBootTest(classes = App.class)
class TeststarterApplicationTests {
@Autowired
DemoService demoService;
@Test
public void contextLoads() {
System.out.println(demoService.doSomething());
}
}
執行運行結果如下:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.1.RELEASE)
2019-12-03 15:16:57.423 INFO 19712 --- [ main] c.e.t.TeststarterApplicationTests : Starting TeststarterApplicationTests on Wangxinyao with PID 19712 (started by Administrator in E:\IDEAWorkSpace\teststarter)
2019-12-03 15:16:57.430 INFO 19712 --- [ main] c.e.t.TeststarterApplicationTests : No active profile set, falling back to default profiles: default
2019-12-03 15:17:00.216 INFO 19712 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-12-03 15:17:00.754 INFO 19712 --- [ main] c.e.t.TeststarterApplicationTests : Started TeststarterApplicationTests in 4.157 seconds (JVM running for 6.18)
Wang sir do Coding !
2019-12-03 15:17:01.054 INFO 19712 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
結語:基本上對於自定義Starter配置的講解就到這裏了,通過自定義Starter,可以把之前的項目通過打包注入到新的項目中,便捷開發