自定義hello-spring-booter-starter
1概述
1.1 SpringBoot核心原理
springboot的核心有如下四點:
① 起步依賴
核心是依賴傳遞,官方集成的第三方框架,從而實現(xiàn)版本管理
② 自動配置管理
通過springboot自動配置管理特性將其實例化到(自定義)類中程序啟動時,向Spring容器中導(dǎo)入很多配置,代替繁瑣的xml或注入Bean。注解中加入EnableConfigurationProperties,application.yml中的所有配置文件都會指向?qū)嶓w類。如server.port對應(yīng)的實體類ServerProperties(掃描包路徑為:org.springframework.boot.autoconfigure),
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
③ 運行監(jiān)控管理Actuator
④ 命令行工具cli
可以使用SpringBoot快速的開發(fā)基于Spring框架的項目。由于圍繞SpringBoot存在很多開箱即用的Starter依賴,使得我們在開發(fā)業(yè)務(wù)代碼時能夠非常方便的、不需要過多關(guān)注框架的配置,而只需要關(guān)注業(yè)務(wù)即可。
1.2 常用的幾個注解說明
@Configuration:表明此類是一個配置類,將變?yōu)橐粋€bean被spring進(jìn)行管理。
@EnableConfigurationProperties:啟用屬性配置,將讀取HelloServiceProperties里面的屬性。
@ConditionalOnClass:當(dāng)類路徑下面有HelloServiceConfiguration此類時,自動配置。
@ConditionalOnProperty:判斷指定的屬性是否具備指定的值。
@ConditionalOnMissingBean:當(dāng)容器中沒有指定bean是,創(chuàng)建此bean。
@ConditionalOnBean:當(dāng)容器中有指定的Bean的條件下
@ConditionalOnClass:當(dāng)類路徑下有指定的類的條件下
@ConditionalOnExpression:基于SpEL表達(dá)式作為判斷條件
@ConditionalOnJava:基于JVM版本作為判斷條件
@ConditionalOnJndi:在JNDI存在的條件下查找指定的位置
@ConditionalOnMissingBean:當(dāng)容器中沒有指定Bean的情況下
@ConditionalOnMissingClass:當(dāng)類路徑下沒有指定的類的條件下
@ConditionalOnNotWebApplication:當(dāng)前項目不是Web項目的條件下
@ConditionalOnProperty:指定的屬性是否有指定的值
@ConditionalOnResource:類路徑下是否有指定的資源
@ConditionalOnSingleCandidate:當(dāng)指定的Bean在容器中只有一個,或者在有多個Bean的情況下,用來指定首選的Bean @ConditionalOnWebApplication:當(dāng)前項目是Web項目的條件下
1.3 @EnableAutoC vs @ImportAutoConfiguration
使用@EnableAutoConfiguration時會掃描整個類路徑下,包括依賴引入的jar包所有的自動配置類(被注解了@Configuration的類),嘗試進(jìn)行自動配置。比如,tomcat-embedded.jar。
而@ImportAutoConfiguration只運行在你注解中提供的配置類。
下面是一個Spring Boot入口方法中使用@ImportAutoConfiguration的列子:
@ComponentScan("path.to.your.controllers")
@ImportAutoConfiguration({
WebMvcAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class,
ServerPropertiesAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class
})
public class App {

2自定義boot-starter
遵循springboot官方建議對于非官方的starter命名方式為xxx-spring-boot-starter,所以本工程名為hello-spring-boot-starter。
2.1實現(xiàn)原理
我們知道使用一個公用的starter的時候,只需要將相應(yīng)的依賴添加的Maven的配置文件當(dāng)中即可,免去了自己需要引用很多依賴類,并且SpringBoot會自動進(jìn)行類的自動配置。那么 SpringBoot 是如何知道要實例化哪些類,并進(jìn)行自動配置的呢,分如下三步驟:
1.SpringBoot 在啟動時會去依賴的starter包中尋找 resources/META-INF/spring.factories 文件,然后根據(jù)文件中配置的Jar包去掃描項目所依賴的Jar包,這類似于 Java 的 SPI 機(jī)制。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.kikop.boot.HelloServiceAutoConfiguration
2.根據(jù)spring.factories配置加載AutoConfiguration類。
3.根據(jù) @Conditional注解的條件,進(jìn)行自動配置并將Bean注入Spring Context 上下文當(dāng)中。我們也可以使用@ImportAutoConfiguration({HelloServiceAutoConfiguration.class}) 指定自動配置哪些類。
2.2實現(xiàn)步驟
2.2.1創(chuàng)建maven
<?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.kikop.boot</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--業(yè)務(wù)系統(tǒng)中添加-->
<!--作用是編譯時生成 spring-configuration-metadata.json ,-->
<!--此文件主要給IDE使用。如當(dāng)配置此jar相關(guān)配置屬性在 application.yml ,-->
<!--你可以用ctlr+鼠標(biāo)左鍵點擊屬性名,IDE會跳轉(zhuǎn)到你配置此屬性的類中。-->
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-configuration-processor</artifactId>-->
<!--<optional>true</optional>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2.2配置文件讀取類
package com.kikop.boot.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
@author kikop
@version 1.0
@project Name: hello-spring-bootstarter
@file Name: HelloServiceProperties
@desc 功能描述 配置文件讀取類
對應(yīng)yml配置文件總的屬性,配置此注解可以自動導(dǎo)入application.properties配置文件中的屬性
@date 2020/2/20
@time 7:33
@by IDE: IntelliJ IDEA
*/
@ConfigurationProperties(prefix = HelloServiceProperties.PREFIX,ignoreUnknownFields = true)
public class HelloServiceProperties {
public static final String PREFIX = "com.kikop.boot";
// 定義jar包中默認(rèn)的配置屬性:name
private String name = "hello";
// 定義jar包中默認(rèn)的配置屬性:hobby
private String hobby = "springboot";
// 定義jar包中默認(rèn)的配置屬性:place
private String place="nj";
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
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;
}
}
2.2.3業(yè)務(wù)實體類
package com.kikop.boot.entity;
import org.springframework.util.StringUtils;
/**
@author kikop
@version 1.0
@project Name: hello-spring-bootstarter
@file Name: HelloServiceInfo
@desc 功能描述 Starter要實現(xiàn)的功能
已基于業(yè)務(wù)轉(zhuǎn)化的包裝類
@date 2020/2/20
@time 7:36
@by IDE: IntelliJ IDEA
*/
public class HelloServiceInfo {
//姓名
private String name;
//愛好(多個逗號分隔)
private String hobby;
//住址
private String place;
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public String getName() {
return "name is " + name;
}
public String getHobby() {
return "hobby is " + hobby;
}
public void setName(String name) {
this.name = name;
}
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String[] split(String separatorChar) {
return StringUtils.split(this.getHobby(), separatorChar);
}
@Override
public String toString() {
return "HelloServiceInfo{" +
"name='" + name + '\'' +
", hobby='" + hobby + '\'' +
", place='" + place + '\'' +
'}';
}
}
2.2.4自動配置類
package com.kikop.boot;
import com.kikop.boot.entity.HelloServiceInfo;
import com.kikop.boot.properties.HelloServiceProperties;
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;
/**
@author kikop
@version 1.0
@project Name: hello-spring-bootstarter
@file Name: HelloServiceAutoConfiguration
@desc 功能描述 自動配置類
@date 2020/2/20
@time 7:37
@by IDE: IntelliJ IDEA
*/
// 1.Configuration 表明此類是一個配置類,將變?yōu)橐粋€bean被spring進(jìn)行管理
@Configuration
// 2.當(dāng)類路徑下面有HelloServiceInfo此類時,自動配置
@ConditionalOnClass(HelloServiceInfo.class)
// 3.啟用屬性配置,將讀取 HelloServiceProperties 里面的屬性
@EnableConfigurationProperties(HelloServiceProperties.class)
//// 4.判斷指定的屬性是否具備指定的值(放類上)
//@ConditionalOnProperty(prefix = "com.kikop.boot", value = "enabled", matchIfMissing = true)
public class HelloServiceAutoConfiguration {
/**
* 注入讀取的 HelloServiceProperties
*/
@Autowired
private HelloServiceProperties helloServiceProperties;
/**
* 注入Bean,已基于業(yè)務(wù)轉(zhuǎn)化的包裝類
* @return
*/
@Bean
@ConditionalOnMissingBean(HelloServiceInfo.class)
// 4.判斷指定的屬性是否具備指定的值(放Bean上)
// 當(dāng)配置文件中 com.kikop.boot.enabled=true
@ConditionalOnProperty(prefix = "com.kikop.boot", value = "enabled",matchIfMissing = true)
public HelloServiceInfo helloServiceInfo() {
HelloServiceInfo helloServiceInfo=new HelloServiceInfo();
helloServiceInfo.setName(helloServiceProperties.getName());
helloServiceInfo.setHobby(helloServiceProperties.getHobby());
helloServiceInfo.setPlace(helloServiceProperties.getPlace());
return helloServiceInfo;
}
}
2.2.5spring.factories
文件位置:resorces\META-INF\spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.kikop.boot.HelloServiceAutoConfiguration
2.3測試
2.3.1加入依賴
<dependency>
<groupId>com.kikop.boot</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2.3.2 controller
@Autowired
HelloServiceInfo helloServiceInfo;
@RequestMapping(value = "/hello")
public String hello() {
return helloServiceInfo.toString();
}
2.3.3 application.yml
com:
kikop:
boot:
enable: true
name: kikop11
hobby: tabletennis
place: nj
2.3.4調(diào)用
HelloServiceInfo{name='kikop', hobby='tabletennis', place='nj'}
參考
- Springcloud
<u>https://spring.io/projects/spring-cloud</u>
<u>https://start.spring.io/</u>
- SpringBoot啟動過程分析
<u>http://www.itdecent.cn/p/603d125f21b3</u>
- SpringBoot啟動類圖
<u>https://www.processon.com/view/link/59812124e4b0de2518b32b6e</u>
- 使用springboot自定義starter實例1
<u>https://blog.csdn.net/qq_21150865/article/details/83504780</u>