日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
手把手帶你開發(fā)Starter,點(diǎn)對(duì)點(diǎn)帶你講解原理
_____            _             ____              _   
/ ____| (_) | _ \ | |
| (___ _ __ _ __ _ _ __ __ _| |_) | ___ ___ | |_
\___ \| '_ \| '__| | '_ \ / _` | _ < / _ \ / _ \| __|
____) | |_) | | | | | | | (_| | |_) | (_) | (_) | |_
|_____/| .__/|_| |_|_| |_|\__, |____/ \___/ \___/ \__|
| | __/ |
|_| |___/

為什么要用Starter?

創(chuàng)新互聯(lián)公司專注于項(xiàng)城網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供項(xiàng)城營銷型網(wǎng)站建設(shè),項(xiàng)城網(wǎng)站制作、項(xiàng)城網(wǎng)頁設(shè)計(jì)、項(xiàng)城網(wǎng)站官網(wǎng)定制、小程序定制開發(fā)服務(wù),打造項(xiàng)城網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供項(xiàng)城網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

現(xiàn)在我們就來回憶一下,在還沒有Spring-boot框架的時(shí)候,我們使用Spring 開發(fā)項(xiàng)目,如果需要某一個(gè)框架,例如mybatis,我們的步驟一般都是:

到maven倉庫去找需要引入的mybatis jar包,選取合適的版本(易發(fā)生沖突)

到maven倉庫去找mybatis-spring整合的jar包,選取合適的版本(易發(fā)生沖突)

在spring的applicationContext.xml文件中配置dataSource和mybatis相關(guān)信息

假如所有工作都到位,一般可以一氣呵成;但很多時(shí)候都會(huì)花一堆時(shí)間解決jar 沖突,配置項(xiàng)缺失,導(dǎo)致怎么都啟動(dòng)不起來等等,各種問題。

所以在2012 年 10 月,一個(gè)叫 Mike Youngstrom 的人在 Spring Jira 中創(chuàng)建了一個(gè)功能請(qǐng)求,要求在 Spring Framework 中支持無容器 Web 應(yīng)用程序體系結(jié)構(gòu),提出了在主容器引導(dǎo) Spring 容器內(nèi)配置 Web 容器服務(wù);這件事情對(duì) SpringBoot 的誕生應(yīng)該說是起到了一定的推動(dòng)作用。

所以SpringBoot 設(shè)計(jì)的目標(biāo)就是簡化繁瑣配置,快速建立Spring 應(yīng)用。

然后在開發(fā)Spring-boot 應(yīng)用的是時(shí)候, 經(jīng)??梢钥吹轿覀兊膒om 文件中引入了spring-boot-starter-web、spring-boot-starter-data-redis、mybatis-spring-boot-starter 這樣的依賴,然后幾乎不用任何配置就可以使用這些依賴的功能,真正的感受到了開箱即用的爽。

下面我們就先來嘗試自己開發(fā)一個(gè)Starter。

  1. 命名規(guī)范

在使用spring-boot-starter,會(huì)發(fā)現(xiàn),有的項(xiàng)目名稱是 XX-spring-boot-starter,有的是spring-boot-starter-XX,這個(gè)項(xiàng)目的名稱有什么講究呢?從springboot官方文檔摘錄:

這段話的大概意思就是,麻煩大家遵守這個(gè)命名規(guī)范:

Srping官方命名格式為:spring-boot-starter-{name}

非Spring官方建議命名格式:{name}-spring-boot-starter

  1. 開發(fā)示例

下面我就以記錄日志的一個(gè)組件為示例來講述開發(fā)一個(gè)starter 的過程。

  1. 新建工程

首先新建一個(gè)maven 工程,名稱定義為
jd-log-spring-boot-starter

  1. Pom 引入依賴

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0

org.springframework.boot
spring-boot-starter-parent
2.5.13


com.jd
jd-log-spring-boot-starter
1.0-SNAPSHOT
jd-log-spring-boot-starter
http://www.example.com

UTF-8
1.8
1.8






org.springframework.boot
spring-boot-autoconfigure



org.springframework.boot
spring-boot-configuration-processor



org.springframework.boot
spring-boot-starter-aop


org.projectlombok
lombok





org.apache.maven.plugins
maven-source-plugin
2.2.1


attach-sources

jar-no-fork






這邊稍微解釋一下這幾個(gè)依賴:

spring-boot-autoconfigure :提供自動(dòng)化裝配功能,是為了Spring Boot 應(yīng)用在各個(gè)模塊提供自動(dòng)化配置的作用;即加入對(duì)應(yīng) pom,就會(huì)有對(duì)應(yīng)配置其作用;所以我們想要自動(dòng)裝配功能,就需要引入這個(gè)依賴。

spring-boot-configuration-processor:將自定義的配置類生成配置元數(shù)據(jù),所以在引用自定義STARTER的工程的YML文件中,給自定義配置初始化時(shí),會(huì)有屬性名的提示;確保在使用@ConfigurationProperties注解時(shí),可以優(yōu)雅的讀取配置信息,引入該依賴后,IDEA不會(huì)出現(xiàn)“spring boot configuration annotation processor not configured”的錯(cuò)誤;編譯之后會(huì)在META-INF 下生成一個(gè)
spring-configuration-metadata.json 文件,大概內(nèi)容就是定義的配置的元數(shù)據(jù);效果如下截圖。

spring-boot-starter-aop :這個(gè)就不用解釋了,因?yàn)槭纠怯涗浫罩?,我們用到切面的功能,所以需要引入?/p>

  1. 定義屬性配置
/**
* @author kongxiangdong2
* @Title: LogProperties
* @ProjectName jd-log-spring-boot-starter
* @Description: TODO
* @date
@ConfigurationProperties(prefix = "jd")
@Data
public class LogProperties {


/**
* 是否開啟日志
*/
private boolean enable;


/**
* 平臺(tái):不同服務(wù)使用的區(qū)分,默認(rèn)取 spring.application.name
*/
@Value("${spring.application.name:#{null}}")
private String platform;

@ConfigurationProperties:該注解和@Value 注解作用類似,用于獲取配置文件中屬性定義并綁定到Java Bean 或者屬性中;換句話來說就是將配置文件中的配置封裝到JAVA 實(shí)體對(duì)象,方便使用和管理。

這邊我們定義兩個(gè)屬性,一個(gè)是是否開啟日志的開關(guān),一個(gè)是標(biāo)識(shí)平臺(tái)的名稱。

  1. 定義自動(dòng)配置類
/**
* @author kongxiangdong2
* @Title: JdLogAutoConfiguration
* @ProjectName jd-log-spring-boot-starter
* @Description: TODO
* @date 2022/9/110:06
*/
@Configuration
@ComponentScan("com.jd")
@ConditionalOnProperty(prefix = "jd",name = "enable",havingValue = "true",matchIfMissing = false)
@EnableConfigurationProperties({LogProperties.class})
public class JdLogAutoConfiguration {


//
}

這個(gè)類最關(guān)鍵了,它是整個(gè)starter 最重要的類,它就是將配置自動(dòng)裝載進(jìn)spring-boot的;具體是怎么實(shí)現(xiàn)的,下面在講解原理的時(shí)候會(huì)再詳細(xì)說說,這里先完成示例。

@Configuration :這個(gè)就是聲明這個(gè)類是一個(gè)配置類

@ConditionalOnProperty:作用是可以指定prefix.name 配置文件中的屬性值來判定configuration是否被注入到Spring,就拿上面代碼的來說,會(huì)根據(jù)配置文件中是否配置jd.enable 來判斷是否需要加載JdLogAutoConfiguration 類,如果配置文件中不存在或者配置的是等于false 都不會(huì)進(jìn)行加載,如果配置成true 則會(huì)加載;指定了havingValue,要把配置項(xiàng)的值與havingValue對(duì)比,一致則加載Bean;配置文件缺少配置,但配置了matchIfMissing = true,加載Bean,否則不加載。

在這里稍微擴(kuò)展一下經(jīng)常使用的Condition

注解

類型

說明

@ConditionalOnClass

Class Conditions類條件注解

當(dāng)前classpath下有指定類才加載

@ConditionalOnMissingClass

Class Conditions類條件注解

當(dāng)前classpath下無指定類才加載

@ConditionalOnBean

Bean ConditionsBean條件注解

當(dāng)期容器內(nèi)有指定bean才加載

@ConditionalOnMissingBean

Bean ConditionsBean條件注解

當(dāng)期容器內(nèi)無指定bean才加載

@ConditionalOnProperty

Property Conditions環(huán)境變量條件注解(含配置文件)

prefix 前綴name 名稱havingValue 用于匹配配置項(xiàng)值matchIfMissing 沒找指定配置項(xiàng)時(shí)的默認(rèn)值

@ConditionalOnResource

ResourceConditions 資源條件注解

有指定資源才加載

@ConditionalOnWebApplication

Web Application Conditionsweb條件注解

是web才加載

@ConditionalOnNotWebApplication

Web Application Conditionsweb條件注解

不是web才加載

@ConditionalOnExpression

SpEL Expression Conditions

符合SpEL 表達(dá)式才加載

@
EnableConfigurationProperties使@ConfigurationProperties 注解的類生效。

  1. 配置EnableAutoConfiguration

在resources/META-INF/ 目錄新建spring.factories 文件,配置內(nèi)容如下;

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jd.JdLogAutoConfiguration

好了,至此自定義Starter 大體框架已經(jīng)好了,下面就是我們記錄日志的功能。

  1. 業(yè)務(wù)功能實(shí)現(xiàn)

首先我們先定義一個(gè)注解Jdlog

/**
* @author kongxiangdong2
* @Title: Jdlog
* @ProjectName jd-log-spring-boot-starter
* @Description: TODO
* @date 2022/9/110:04
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Jdlog {
}

定義切面執(zhí)行邏輯,這邊就簡單的打印一下配置文件的屬性值+目標(biāo)執(zhí)行方法+耗時(shí)。

import com.jd.annotation.Jdlog;
import com.jd.config.LogProperties;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;


/**
* @author kongxiangdong2
* @Title: LogAspectjProcess
* @ProjectName jd-log-spring-boot-starter
* @Description: TODO
* @date
@Aspect
@Component
@Slf4j
@AllArgsConstructor
public class LogAspectjProcess {


LogProperties logProperties;


/**
* 定義切點(diǎn)
*/
@Pointcut("@annotation(com.jd.annotation.Jdlog)")
public void pointCut(){}


/**
* 環(huán)繞通知
*
* @param thisJoinPoint
* @param jdlog
* @return
@Around("pointCut() && @annotation(jdlog)")
public Object around(ProceedingJoinPoint thisJoinPoint, Jdlog jdlog){


//執(zhí)行方法名稱
String taskName = thisJoinPoint.getSignature()
.toString().substring(
thisJoinPoint.getSignature()
.toString().indexOf(" "),
thisJoinPoint.getSignature().toString().indexOf("("));
taskName = taskName.trim();
long time = System.currentTimeMillis();
Object result = null;
try {
result = thisJoinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
log.info("{} -- method:{} run :{} ms",logProperties.getPlatform(), taskName,
(System.currentTimeMillis() - time));
return result;


整體項(xiàng)目結(jié)構(gòu)就是這樣子

好了,現(xiàn)在就可以打包編譯安裝

  1. 測試使用

然后就可以在其他項(xiàng)目中引入使用了;下面以一個(gè)簡單的spring-boot web 項(xiàng)目做個(gè)測試,在pom 中引入下面的依賴配置。

  
com.jd
jd-log-spring-boot-starter
1.0-SNAPSHOT

增加一個(gè)http 訪問的方法,標(biāo)注上@Jdlog 注解

application.yaml 文件中配置

jd:
enable: true
platform: "測試項(xiàng)目"

啟動(dòng)測試,訪問地址http://localhost:8080/test/method1,控制臺(tái)打印如下:

咋樣,自定義的Starter是不是特別的簡單啊,快動(dòng)手試試吧!

上面我們講的都是怎么去開發(fā)一個(gè)starter,但是到底為什么要這樣,spring-boot 是如何去實(shí)現(xiàn)的?是不是還不知道?那下面我們就來說說;

  1. 原理講解

我們上面已經(jīng)看到一個(gè)starter,只需要引入到pom 文件中,再配置一下(其實(shí)都可以不配置)jd.enable=true,就可以直接使用記錄日志的功能了,Spring-boot 是怎么做到的?

在開始的時(shí)候說過,Spring-boot 的好處就是可以自動(dòng)裝配。那下面我就來說說自動(dòng)裝配的原理。

相比于傳統(tǒng)Spring 應(yīng)用,我們搭建一個(gè)SpringBoot 應(yīng)用,我們只需要引入一個(gè)注解(前提:引入springBoot y依賴)@SpringBootApplication,就可以直接運(yùn)行;所以我們就從這個(gè)注解開始入手,看看這個(gè)注解到底做了寫什么?

SpringBootApplication 注解

點(diǎn)開@SpringBootApplication注解可以看到包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan三個(gè)注解。

前面的四個(gè)注解就不用過多敘述了,是定義注解最基本的,關(guān)鍵在于后面的三個(gè)注解:@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan,其實(shí)也就是說在啟動(dòng)類上如果不使用@SpringBootApplication 這個(gè)復(fù)合注解,直接使用者三個(gè)注解一樣可以達(dá)到相同的效果。

@SpringBootConfiguration 注解:我們?cè)俅吸c(diǎn)進(jìn)去看這個(gè)注解,其實(shí)它就是一個(gè)@Configuration 注解。

@ComponentScan 注解

@ComponentScan 注解:配置包掃描定義的掃描路徑,把符合掃描規(guī)則的類裝配到spring容器

@EnableAutoConfiguration 注解

@EnableAutoConfiguration 打開自動(dòng)裝配(自動(dòng)配置著重來看該注解)

注解

作用

解釋

@SpringBootConfiguration

標(biāo)記當(dāng)前類為配置類

加上這個(gè)注解就是為了讓當(dāng)前類作為一個(gè)配置類交由 Spring 的 IOC 容器進(jìn)行管理,因?yàn)榍懊嫖覀冋f了,SpringBoot 本質(zhì)上還是 Spring,所以原屬于 Spring 的注解 @Configuration 在 SpringBoot 中也可以直接應(yīng)用

@ComponentScan

配置包掃描定義的掃描路徑,把符合掃描規(guī)則的類裝配到spring容器

用于定義 Spring 的掃描路徑,等價(jià)于在 xml 文件中配置 ,假如不配置掃描路徑,那么 Spring 就會(huì)默認(rèn)掃描當(dāng)前類所在的包及其子包中的所有標(biāo)注了 @Component,@Service,@Controller 等注解的類。

@EnableAutoConfiguration

打開自動(dòng)裝配

下面著重講解

我們?cè)俅吸c(diǎn)擊@EnableAutoConfiguration進(jìn)入查看,它是一個(gè)由 @AutoConfigurationPackage 和 @Import 注解組成的復(fù)合注解;

首先我們先來看@Import 這個(gè)注解,這個(gè)是比較關(guān)鍵的一個(gè)注解;

在說這個(gè)注解之前我們先舉個(gè)例子,假如我們有一個(gè)類Demo,它是一個(gè)不在啟動(dòng)配置類目錄之下的,也就意味著它不會(huì)被掃描到,Spring 也無法感知到它的存在,那么如果需要能將它被掃描到,是不是我們可以通過加@Import 注解來導(dǎo)入Demo 類,類似如下代碼

@Configuration
@Import(Demo.class)
public class MyConfiguration {
}

所以,我們可以知道@Import 注解其實(shí)就是為了去導(dǎo)入一個(gè)類。所以這里@Import({
AutoConfigurationImportSelector.class}) 就是為了導(dǎo)入AutoConfigurationImportSelector 類,那我們繼續(xù)來看這個(gè)類,AutoConfigurationImportSelector實(shí)現(xiàn)的是DeferredImportSelector接口,這是一個(gè)延遲導(dǎo)入的類;再細(xì)看會(huì)有一個(gè)方法比較顯眼,根據(jù)注解元數(shù)據(jù)來選擇導(dǎo)入組件,當(dāng)注解元數(shù)據(jù)空,直接返回一個(gè)空數(shù)組;否則就調(diào)用getAutoConfigurationEntry ,方法中會(huì)使用AutoConfigurationEntry的getConfigurations(),configurations是一個(gè)List,那么我們看下AutoConfigurationEntry是怎么生成的。

進(jìn)入到getAutoConfigurationEntry 方法中可以看到主要是getCandidateConfigurations 來獲取候選的 Bean,并將其存為一個(gè)集合;后續(xù)的方法都是在去重,校驗(yàn)等一系列的操作。

我們繼續(xù)往
getCandidateConfigurations 方法里看,最終通過SpringFactoriesLoader.loadFactoryNames來獲取最終的configurations,并且可以通過斷言發(fā)現(xiàn)會(huì)使用到META-INF/spring.factories文件,那么我們?cè)龠M(jìn)入SpringFactoriesLoader.loadFactoryNames()中來看下最終的實(shí)現(xiàn)。

SpringFactoriesLoader.loadFactoryNames()方法會(huì)讀取META-INF/spring.factories文件下的內(nèi)容到Map中,再結(jié)合傳入的factoryType=EnableAutoConfiguration.class,因此會(huì)拿到 org.springframework.boot.autoconfigure.EnableAutoConfiguration為key對(duì)應(yīng)的各個(gè)XXAutoConfiguration的值,然后springboot在結(jié)合各個(gè)starter中的代碼完成對(duì)于XXAutoConfiguration中的Bean的加載動(dòng)作。

這邊再擴(kuò)展一下這個(gè)內(nèi)容,通過 SpringFactoriesLoader 來讀取配置文件 spring.factories 中的配置文件的這種方式是一種 SPI 的思想。

@AutoConfigurationPackage 注解

進(jìn)入這個(gè)注解看,其實(shí)它就是導(dǎo)入了Registrar 這個(gè)類

再進(jìn)入這個(gè)類查看,它其實(shí)是一個(gè)內(nèi)部類,看代碼的大概意思就是讀取到我們?cè)谧钔鈱拥?@SpringBootApplication 注解中配置的掃描路徑(沒有配置則默認(rèn)當(dāng)前包下),然后把掃描路徑下面的Bean注冊(cè)到容器中;

總結(jié)

好了,現(xiàn)在我們大概來理一下整個(gè)自動(dòng)裝配的流程:

  1. 啟動(dòng)類中通過使用@SpringBootApplication實(shí)現(xiàn)自動(dòng)裝配的功能;
  2. 實(shí)際注解@SpringBootApplication是借助注解@EnableAutoConfiguration的功能。
  3. 在注解@EnableAutoConfiguration中又有兩個(gè)注解,@AutoConfigurationPackage,@EnableAutoConfiguration。
  4. 通過@AutoConfigurationPackage實(shí)現(xiàn)對(duì)于當(dāng)前項(xiàng)目中Bean的進(jìn)行加載;
  5. @EnableAutoConfiguration通過@Import({AutoConfigurationImportSelector.class})實(shí)現(xiàn)對(duì)于Pom引入的start中的XXAutoConfiguration的加載;
  6. @AutoConfigurationImportSelector類中通過SpringFactoriesLoader讀取 META-INF/spring.factories中key為org.springframework.boot.autoconfigure.EnableAutoConfiguration對(duì)應(yīng)的各個(gè)XXAutoConfiguration的值,然后springboot在結(jié)合各個(gè)start中的代碼完成對(duì)于XXAutoConfiguration中的Bean的加載動(dòng)作;

到這里是不是已經(jīng)可以很了然對(duì)我們之前開發(fā)starter中的定義了啊,趕緊試試吧


網(wǎng)站名稱:手把手帶你開發(fā)Starter,點(diǎn)對(duì)點(diǎn)帶你講解原理
瀏覽地址:http://www.5511xx.com/article/cddccdc.html