javascript
只需 4 步,自己搞个 Spring Boot Starter!
引言
只要你用Springboot,一定會(huì)用到各種spring-boot-starter。其實(shí)寫(xiě)一個(gè)spring-boot-starter,僅需4步。下面我們就寫(xiě)一個(gè)starter,它將實(shí)現(xiàn),在日志中打印方法執(zhí)行時(shí)間。
“推薦一個(gè)艿艿寫(xiě)的 6000+ Star 的 SpringBoot + SpringCloud + Dubbo 教程的倉(cāng)庫(kù):https://github.com/YunaiV/SpringBoot-Labs
第一步 創(chuàng)建maven項(xiàng)目
在使用spring-boot-starter,會(huì)發(fā)現(xiàn),有的項(xiàng)目名稱(chēng)是 XX-spring-boot-starter,有的是
spring-boot-starter-XX,這個(gè)項(xiàng)目的名稱(chēng)有什么講究呢?
從springboot官方文檔摘錄如下:
“
Do not start your module names with spring-boot, even if you use a different Maven groupId. We may offer official support for the thing you auto-configure in the future.
As a rule of thumb, you should name a combined module after the starter.
從這段話可以看出spring-boot-starter命名的潛規(guī)則。
命名潛規(guī)則
spring-boot-starter-XX是springboot官方的starter
XX-spring-boot-starter是第三方擴(kuò)展的starter
打印方法執(zhí)行時(shí)間的功能,需要用到aop,咱們的項(xiàng)目就叫做
aspectlog-spring-boot-starter吧。
項(xiàng)目的pom文件如下:
<?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>org.example</groupId><artifactId>aspectlog-spring-boot-starter</artifactId><version>1.0.2</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.15.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency></dependencies></project>關(guān)于spring-boot-configuration-processor的說(shuō)明,引自springBoot官方文檔:
“
Spring Boot uses an annotation processor to collect the conditions on auto-configurations in a metadata file ( META-INF/spring-autoconfigure-metadata.properties ). If that file is present, it is used to eagerly filter auto-configurations that do not match, which will improve startup time. It is recommended to add the following dependency in a module that contains auto-configurations:
org.springframework.boot
spring-boot-autoconfigure-processor
true
簡(jiǎn)單說(shuō)就是:寫(xiě)starter時(shí),在pom中配置spring-boot-autoconfigure-processor,在編譯時(shí)會(huì)自動(dòng)收集配置類(lèi)的條件,寫(xiě)到一個(gè)META-INF/spring-autoconfigure-metadata.properties中。
“推薦一個(gè)艿艿寫(xiě)的 3000+ Star 的 SpringCloud Alibaba 電商開(kāi)源項(xiàng)目的倉(cāng)庫(kù):https://github.com/YunaiV/onemall
第二步寫(xiě)自動(dòng)配置邏輯
各種condition
| Class Conditions類(lèi)條件注解 | @ConditionalOnClass | 當(dāng)前classpath下有指定類(lèi)才加載 |
| @ConditionalOnMissingClass | 當(dāng)前classpath下無(wú)指定類(lèi)才加載 | ? |
| Bean ConditionsBean條件注解 | @ConditionalOnBean | 當(dāng)期容器內(nèi)有指定bean才加載 |
| @ConditionalOnMissingBean | 當(dāng)期容器內(nèi)無(wú)指定bean才加載 | ? |
| Property Conditions環(huán)境變量條件注解(含配置文件) | @ConditionalOnProperty | prefix 前綴name 名稱(chēng)havingValue 用于匹配配置項(xiàng)值matchIfMissing 沒(méi)找指定配置項(xiàng)時(shí)的默認(rèn)值 |
| ResourceConditions 資源條件注解 | @ConditionalOnResource | 有指定資源才加載 |
| Web Application Conditionsweb條件注解 | @ConditionalOnWebApplication | 是web才加載 |
| @ConditionalOnNotWebApplication | 不是web才加載 | ? |
| SpEL Expression Conditions | @ConditionalOnExpression | 符合SpEL 表達(dá)式才加載 |
本次我們就選用@ConditionalOnProperty。即配置文件中有aspectLog.enable=true,才加載我們的配置類(lèi)。
下面開(kāi)始寫(xiě)自動(dòng)配置類(lèi)
2.1.定義AspectLog注解,該注解用于標(biāo)注需要打印執(zhí)行時(shí)間的方法。
package?com.shanyuan.autoconfiguration.aspectlog; import?java.lang.annotation.ElementType; import?java.lang.annotation.Retention; import?java.lang.annotation.RetentionPolicy; import?java.lang.annotation.Target; /***?class_name:?ScheduleManage*?describe:???用于控制定時(shí)任務(wù)的開(kāi)啟與關(guān)閉*?對(duì)應(yīng)切面*?creat_user:?wenl*?creat_time:??2018/11/10?18:45**/ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public?@interface???AspectLog?{ }2.2定義配置文件對(duì)應(yīng)類(lèi)
package?com.shanyuan.autoconfiguration.aspectlog; import?org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties("aspectLog") public?class?AspectLogProperties?{private?boolean?enable;public?boolean?isEnable()?{return?enable;}public?void?setEnable(boolean?enable)?{this.enable?=?enable;} }2.3定義自動(dòng)配置類(lèi)
package?com.shanyuan.autoconfiguration.aspectlog;import?org.aspectj.lang.ProceedingJoinPoint; import?org.aspectj.lang.annotation.Around; import?org.aspectj.lang.annotation.Aspect; import?org.slf4j.Logger; import?org.slf4j.LoggerFactory; import?org.springframework.boot.autoconfigure.condition.*; import?org.springframework.context.annotation.Configuration; import?org.springframework.context.annotation.EnableAspectJAutoProxy; import?org.springframework.core.PriorityOrdered;@Aspect @EnableAspectJAutoProxy(exposeProxy?=?true,?proxyTargetClass?=?true) @Configuration @ConditionalOnProperty(prefix?=?"aspectLog",?name?=?"enable",havingValue?=?"true",?matchIfMissing?=?true) public?class?AspectLogAutoConfiguration?implements?PriorityOrdered?{protected?Logger?logger?=?LoggerFactory.getLogger(getClass());@Around("@annotation(com.shanyuan.autoconfiguration.aspectlog.AspectLog)?")public?Object?isOpen(ProceedingJoinPoint?thisJoinPoint)throws?Throwable?{//執(zhí)行方法名稱(chēng)String?taskName?=?thisJoinPoint.getSignature().toString().substring(thisJoinPoint.getSignature().toString().indexOf("?"),thisJoinPoint.getSignature().toString().indexOf("("));taskName?=?taskName.trim();long?time?=?System.currentTimeMillis();Object?result?=?thisJoinPoint.proceed();logger.info("method:{}?run?:{}?ms",?taskName,(System.currentTimeMillis()?-?time));return?result;}@Overridepublic?int?getOrder()?{//保證事務(wù)等切面先執(zhí)行return?Integer.MAX_VALUE;} }配置類(lèi)簡(jiǎn)要說(shuō)明:
@ConditionalOnProperty(prefix?=?"aspectLog",?name?=?"enable",havingValue?=?"true",?matchIfMissing?=?true)當(dāng)配置文件有aspectLog.enable=true時(shí)開(kāi)啟,如果配置文件沒(méi)有設(shè)置aspectLog.enable也開(kāi)啟。
第三步META-INF/spring.factories
META-INF/spring.factories是spring的工廠機(jī)制,在這個(gè)文件中定義的類(lèi),都會(huì)被自動(dòng)加載。多個(gè)配置使用逗號(hào)分割,換行用\
如果有興趣可以查看這2篇blog:
2.@Enable驅(qū)動(dòng)原理(設(shè)置連接)
3.@EnableAutoConfiguration處理邏輯(設(shè)置連接)
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.shanyuan.autoconfiguration.aspectlog.AspectLogAutoConfiguration第四步打包測(cè)試
這是我們最終的目錄結(jié)構(gòu)
在IDEA中,進(jìn)行mvn intall
打包完成后,在其他項(xiàng)目中的pom中引入進(jìn)行測(cè)試
參考資料
-
https://docs.spring.io/spring-boot/docs/2.1.15.RELEASE/reference/html/boot-features-developing-auto-configuration.html#boot-features-custom-starter
總結(jié)
以上是生活随笔為你收集整理的只需 4 步,自己搞个 Spring Boot Starter!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Java 强、弱、软、虚,你属于哪一种?
- 下一篇: 项目实践:Spring Boot 三招组