<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          僅需四步,寫一個(gè) Spring Boot Starter

          共 5815字,需瀏覽 12分鐘

           ·

          2020-10-11 14:31

          Java技術(shù)棧

          www.javastack.cn

          關(guān)注閱讀更多優(yōu)質(zhì)文章


          引言

          只要你用 Spring boot,一定會(huì)用到各種 spring-boot-starter。其實(shí)寫一個(gè)spring-boot-starter,僅需4步。

          下面我們就寫一個(gè)starter,它將實(shí)現(xiàn),在日志中打印方法執(zhí)行時(shí)間。

          第一步 創(chuàng)建maven項(xiàng)目

          在使用spring-boot-starter,會(huì)發(fā)現(xiàn),有的項(xiàng)目名稱是 XX-spring-boot-starter,有的是spring-boot-starter-XX,這個(gè)項(xià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ī)則。

          spring-boot-starter-XX是springboot官方的starter

          XX-spring-boot-starter是第三方擴(kuò)展的starter

          打印方法執(zhí)行時(shí)間的功能,需要用到aop,咱們的項(xiàng)目就叫做

          aspectlog-spring-boot-starter吧。

          項(xiàng)目的pom文件如下:

          "1.0"?encoding="UTF-8"?>
          "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">
          ????4.0.0

          ????org.example
          ????aspectlog-spring-boot-starter
          ????1.0.2
          ????
          ????????org.springframework.boot
          ????????spring-boot-starter-parent
          ????????2.1.15.RELEASE
          ????

          ????
          ????
          ????????
          ????????????org.springframework.boot
          ????????????spring-boot-autoconfigure
          ????????

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

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

          ????



          關(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ō)就是 寫starter時(shí),在pom中配置 spring-boot-autoconfigure-processor,

          在編譯時(shí)會(huì)自動(dòng)收集配置類的條件,寫到一個(gè) META-INF/spring-autoconfigure-metadata.properties中。

          不熟悉 Spring Boot 基礎(chǔ)的可以看下這個(gè)倉(cāng)庫(kù):https://github.com/javastacks/spring-boot-best-practice

          第二步寫自動(dòng)配置邏輯

          各種condition

          類型注解說(shuō)明

          Class Conditions

          類條件注解

          @ConditionalOnClass

          當(dāng)前classpath下

          有指定類才加載

          @ConditionalOnMissingClass

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


          Bean Conditions

          Bean條件注解

          @ConditionalOnBean

          當(dāng)期容器內(nèi)有

          指定bean才加載

          @ConditionalOnMissingBean

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


          Property Conditions

          環(huán)境變量條件

          注解(含配置文件)

          @ConditionalOnProperty

          prefix??前綴

          name?名稱

          havingValue

          ?用于匹配配置項(xiàng)值

          matchIfMissing??

          沒(méi)找指定配置項(xiàng)時(shí)

          的默認(rèn)值

          Resource?Conditions?

          資源條件注解

          @ConditionalOnResource有指定資源才加載

          Web Application Conditions

          web條件注解

          @ConditionalOnWebApplication是web才加載
          @ConditionalOnNotWebApplication不是web才加載
          SpEL Expression Conditions@ConditionalOnExpression符合SpEL 表達(dá)式才加載

          本次我們就選用@ConditionalOnProperty。即配置文件中有aspectLog.enable=true,才加載我們的配置類。

          不熟悉 Spring Boot 基礎(chǔ)的可以看下這個(gè)倉(cāng)庫(kù):https://github.com/javastacks/spring-boot-best-practice

          下面開(kāi)始寫自動(dòng)配置類

          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)類

          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)配置類

          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í)行方法名稱?
          ????????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;
          ????}
          ????@Override
          ????public?int?getOrder()?{
          ????????//保證事務(wù)等切面先執(zhí)行
          ????????return?Integer.MAX_VALUE;
          ????}
          }

          配置類簡(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)啟。基礎(chǔ)知識(shí)不熟悉的可以關(guān)注公眾號(hào)Java技術(shù)棧回復(fù)boot獲取一份完整教程。

          第三步META-INF/spring.factories

          META-INF/spring.factories是spring的工廠機(jī)制,在這個(gè)文件中定義的類,都會(huì)被自動(dòng)加載。多個(gè)配置使用逗號(hào)分割,換行用\

          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è)試


          作者:溫安適
          來(lái)源:my.oschina.net/floor/blog/4435699




          關(guān)注Java技術(shù)棧看更多干貨



          戳原文,獲取精選面試題!
          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一级成人亚欧精品 | 成人一区二区A片 | 国产娇小13videos糟蹋 | 香蕉人妻AV久久久久天天 | 日本二级黄免费在线观看 |