點擊上方「Java面試進化論」,選擇「設爲星標」html
回覆」666「獲取新整理的面試資料vue
原文 : https://juejin.im/post/6844903923162038279java
SpringBoot中starter真是個好東西,不論是官方提供,仍是自定義,快速集成,真方便!web
日常咱們使用 SpringBoot 開發常常用到一些第三方 jar 包,並且一般只是引入一個xxx-starter
jar 包就擁有了全部功能,到底其中的原理是怎樣的呢?要想知道其中的原理,咱們不妨先本身手動製做一個Starter
,這對咱們深刻使用一些第三框架將會有至關大的幫助。
面試
1、SpringBoot Starter 開發規範
SpringBoot 官網文檔提到的規範大體由下面幾個:spring
一、命名使用
spring-boot-starter-xxx
, 其中xxx
是咱們具體的包名稱,若是集成Spring Cloud
則使用spring-cloud-starter-xxx
sql二、一般須要準備兩個
jar
文件,其中一個不包含任何代碼,只用於負責引入相關以來的 jar 文件,另一個則包含核心的代碼後端
如nacos
與 Spring Cloud 集成的 starter 以下圖:springboot
更多Starter
製做規範,咱們能夠查看官網文檔https://docs.spring.io/spring-boot/docs/2.1.0.RELEASE/reference/htmlsingle/#boot-features-custom-starter微信
2、Starter 開發開發步驟
首先咱們應該先明白 Springboot 加載第三方Starter
的機制,詳情請參考小編的另一篇文章 SpringBoot 啓動源碼分析及相關技巧學習
一、新建一個
Maven
工程,咱們起名爲study-spring-boot-starter
二、引入相關的依賴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!-- 咱們是基於Springboot的應用 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
由於咱們須要用到 Springboot 提供的相關注解,而且使用 springboot 提供的自動配置功能,咱們不得不引入spring-boot-autoconfigure
和spring-boot-dependencies
兩個依賴。
搜索公縱號:MarkerHub,關注回覆[ vue ]獲取先後端入門教程!
三、新建咱們本身的自動配置類
通常來講,咱們可能想在 springboot 啓動的時候就預先注入本身的一些 bean,此時,咱們要新建本身的自動配置類,通常採用xxxxEnableAutoConfiguration
。
下面咱們新建StudyStarterAutoConfiguration.java
package com.example.mystarter.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.example.mystarter.other.Student;
/**
* 存放咱們的配置類,用來配置咱們自定義的bean的。既然是一個配置類,那麼咱們就須要有@Configuration進行聲明
*
* @Author jiawei huang
* @Since 2019年8月23日
* @Version 1.0
*/
@Configuration
// 導入咱們自定義的配置類,供當前類使用
@EnableConfigurationProperties(StudentConfigProperties.class)
// 當存在某個類時,此自動配置類纔會生效,這裏可使用外部的String類名
@ConditionalOnClass(Student.class)
// 只有web應用程序時此自動配置類纔會生效
@ConditionalOnWebApplication
public class StudyStarterAutoConfiguration {
/**
* 當存在study.config.enable=true的配置時,這個Student bean才生效
*
* @return
*/
@Bean
@ConditionalOnProperty(prefix = "study.config", name = "enable", havingValue = "true")
public Student defaultStudent(StudentConfigProperties studyConfigProperties) {
Student student = new Student();
student.setAge(studyConfigProperties.getAge());
student.setName(studyConfigProperties.getName());
return student;
}
}
@Configuration
聲明該類爲一個配置類
@EnableConfigurationProperties
的意思是,將括號內所指定的類注入容器成爲一個 bean 對象,由於通常來講,像 springboot 默認的包掃描路徑爲xxxxxxApplication.java
所在包以及其全部子包, 可是一些第三方的 jar 中的 bean 很明顯不能被掃描到,此時該註解就派上了用場,固然,你可能會說,我使用@ComponentScan
不就好了,這兩個註解的區別是:@ComponentScan
前提是你要的 bean 已經存在 bean 容器中了,而@EnableConfigurationProperties
是要讓容器自動去發現你要類並註冊成爲 bean。
springboot 提供了不少的@Condition
開頭的註解,用於表示當某某條件成立或者不成立時所作的操做。
@ConditionalOnClass
指的是當存在某個類時,此自動配置類StudyStarterAutoConfiguration
纔會生效, 咱們可能會問,咱們有時候想依賴一個第三方的 bean 存在,StudyStarterAutoConfiguration
才生效怎麼辦(好比mybatis
的starter
源碼須要sqlsessionfactorybean
同樣),不用慌,@ConditionalOnClass
也容許咱們指定字符串全路徑,例如@ConditionalOnClass("com.xxx.xxx")
@ConditionalOnWebApplication
表示噹噹前應用是一個 web servlet 應用時,配置類才生效。這也能夠解答爲何 springboot 源碼SpringApplication.java
中有作應用推斷。
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 這裏會去作推斷
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
四、咱們新建一個
StudentConfigProperties.java
,聲明該 starter 的使用者能夠配置哪些配置項。
package com.example.mystarter.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 配置項
*
* @Author jiawei huang
* @Since 2019年8月23日
* @Version 1.0
*/
@ConfigurationProperties(prefix = "study.config")
public class StudentConfigProperties {
private int age;
private String name;
/**
* @return the age
*/
public int getAge() {
return age;
}
/**
* @param age the age to set
*/
public void setAge(int age) {
this.age = age;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "StudentConfigProperties [age=" + age + ", ]";
}
}
五、在
resources
目錄下新建一個META-INF
目錄而且建立一個spring.factories
文件
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.mystarter.config.StudyStarterAutoConfiguration
咱們的自動配置入口類,Springboot 會掃描到這個文件,掃描機制能夠查看小編寫的另一篇博文
3、使用咱們本身的Starter
一、咱們新建另一個 springboot 工程,引入剛剛的
starter
<dependency>
<groupId>com.example</groupId>
<artifactId>study</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
咱們新建一個接口,來測試咱們的 starter 是有有用,代碼以下:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.mystarter.config.StudentConfigProperties;
import com.example.mystarter.other.Student;
/**
*
* @Author jiawei huang
* @Since 2019年8月19日
* @Version 1.0
*/
@RestController
public class MyController {
@Autowired
private Student student;
@Autowired
private StudentConfigProperties studentConfigProperties;
@RequestMapping("/getStudent")
private String getStudent() {
return "name=[" + student.getName() + "],age=[" + student.getAge() + "],studentConfigProperties=["
+ studentConfigProperties + "]";
}
}
啓動咱們的 demo 工程,而後訪問咱們的接口,結果以下:
好了,咱們的 starter 製做到此就結束了,其實很是簡單,我建議在學會製做的基礎上,多看看其餘框架的源碼加以驗證,最好可以也動手實現如下,說不定之後咱們也須要提供一個 starer 給其餘人用呢。有疑問,歡迎評論區交流,謝謝閱讀。
推薦閱讀
1. 面試官 : 如何使用 StringBuider 效率更高?
2. 還不懂Spring Boot啓動原理的話,必定要看看!
3. 面試官 : TCP 鏈接上面能發多少個 HTTP 請求?
4. NullPointerException 的處理新方式, Java14 真的太香了!
回覆"SpringCrm"獲取
SpringBoot 後臺 CRM 項目
好文點個在看吧!
本文分享自微信公衆號 - Java面試進化論(AuditionEvolution)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。