您好,登錄后才能下訂單哦!
如何自定義springboot starter,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
自定義 springboot starter
搞一個demo看看,demo實現了兩個功能:
使用Aspectj方式的aop,來實現對某類函數參數監控;
定義一個自己的配置類,讀取我們在yml或properties里面配置的參數,同時提供一個service,用來獲取我們讀取的結果。
這里是示例工程starter.
看了自動配置原理之后,應該知道META-INF/spring.facotires這個家伙是配置的重點了吧,我們很多個的東西都是在這個里頭。因此,我們自己的stater當然也少不了這個配置文件,先貼個工程結構。
spring-boot-myaop-starter ├─ pom.xml ├─ spring-boot-myaop-starter.iml └─ src/main ├─ java └─ resources └─ META-INF └─ spring.factories
先按照正常工程把一些配置都配好,先來寫一個AspectJ的。
package com.wt.myaop.aspect; @Aspect @Component public class MyAspect { @Pointcut("@annotation(myAnno)") public void myAspectPointCut(MyAopAnnotation myAnno) { } @Before("myAspectPointCut(myAnno)") public void performanceTrance2(JoinPoint joinPoint, MyAopAnnotation myAnno) throws Throwable { System.out.println("--------------myaop-starter args monitor start-----------------"); Object[] args = joinPoint.getArgs(); Class<?>[] types = myAnno.argTypes(); for (int i = 0; i < Math.min(args.length, types.length); i++) { System.out.println("type:" + types[i] + "<--->arg:" + args[i]); } System.out.println("--------------myaop-starter args monitor end-----------------"); } }
我們這里使用的是@Before,在這個方法里面獲取到所有參數,然后將所有參數的類型和值都打印出來,方法前后輸出日志,比較簡單。
然后來看pointCut,這是一個基于注解的,這樣其他項目引入這個starter的時候就可以直接以注解來使用,對其他項目不具有侵入性。所以,我們還需要定義一個注解。
package com.wt.myaop.anno; @Target(ElementType.METHOD) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface MyAopAnnotation { Class<?>[] argTypes() default {}; }
注解里面有屬性,用來定義方法參數的類型順序,當然也可以不需要,放這里只是為了方便。
屬性的讀取我們需要用到一個springboot的注解@ConfigurationProperties.來看看這個配置類,為了縮短代碼長度,都沒有貼getter/setter方法哦。
package com.wt.myaop.config; @ConfigurationProperties(prefix = MyConfig.MY_PREFIX) public class MyConfig { public static final String MY_PREFIX = "myconfig"; /** * 不加該注解也能正常得到值 */ @NestedConfigurationProperty private UserConfig user; private String job; }
代碼中我們定義了一個常量MY_PREFIX,這個是配置文件中的前綴,springboot會讀取這個前綴的配置來注入到這個實體當中,當然,配置肯定不會是在我們這個starter項目中來配置,是我們實際使用的project中配置的哦!要不然我還不如直接寫死,對吧,嘻嘻。
除了基本屬性之外,還提供了一個實體屬性,UserConfig。來看看這個東西吧。
package com.wt.myaop.config; public class UserConfig { private String username; private Integer age; private String sex; }
配置信息的接收實體有了,我們現在來定義一個service,這個service的作用就是注入這個實體,然后輸出配置信息,以檢查我們的配置生效了。service的接口就不貼了哈,只貼實現類了。
package com.wt.myaop.service; public class MyConfigServiceImpl implements MyConfigService { private final MyConfig myconfig; public MyConfigServiceImpl(MyConfig myConfig) { this.myconfig = myConfig; } @Override public void printMyConfig() { System.out.println(myConfig); } }
看構造方法和屬性,構造方法注入了我們的配置,當然,我們如果需要使用這個service,我們就需要手動將這個配置注入進來,以確保service實例化時,myconfig不會為null,里面的方法很簡單,僅僅打印了我們的配置類MyConfig。
starter像這樣就算完了嗎?當然沒有,可以感受到以上這些其實都跟普通的project的配置沒有太多差別,很簡單。
回憶一下我們自動配置的核心是不是叫xxxAutoConfiguration的東西呢?spring.vactories中的哦!
好了,來吧,開始定義我們自己的AutoConfiguration。
package com.wt.myaop.autoconfig; @Configuration @ComponentScan({"com.wt.myaop.aspect"}) @AutoConfigureAfter(AopAutoConfiguration.class) @EnableConfigurationProperties(MyConfig.class) public class MyArgsMonitorAopAutoConfig { private MyConfig myConfig; public MyArgsMonitorAopAutoConfig(MyConfig myConfig) { this.myConfig = myConfig; } @Bean public MyConfigService getMyConfigService(){ return new MyConfigServiceImpl(myConfig); } }
我們現在來研究一下這個類都有什么。
@Configuration: 表明這個類是一個配置類; @ComponentScan: 指出需要掃描的包,可以看到上面掃描的包中包含了Aspect注解的配置,當然使用aop這部分是必不可少的; @AutoConfigureAfter: 指出當前類需要再某個自動配置完成之后才開始配置; @EnableConfigurationProperties: 為@ConfigurationProperties注解提供支持,什么意思呢; 解釋一下這個,把@ConfigurationProperties標注的類(MyConfig)注冊成bean,以支持依賴注入,本身這些類 是不會被注冊成bean的,當然我們可以在配置類上加@Component注解。使用這個注解可以在我們需要某個配置類 注冊成bean的時候,就使用,侵入性小,避免了配置類上加@Component注解。
從上面代碼中可以看到我們的配置類MyConfig通過構造方法被注入到了MyArgsMonitorAopAutoConfig當中,而MyArgsMonitorAopAutoConfig是一個配置類,里面通過@Bean的方式配置了MyConfigService。
看起來很簡答吧,實際上也很簡單,autoConfiguration的配置類就好了,引入這個類,就相當于引入了一個Myconfig的配置類,和一個我們能夠使用的MyConfigService。
自動配置的類有了,需要放到spring.factories中才能生效。
# META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.wt.myaop.autoconfig.MyArgsMonitorAopAutoConfig
這樣starter部分就算是完成了。
Tips: 自動配置其實很簡單,把需要的配置都放到一個叫做starter的工程里面,然后創建一個XxxAutoConfiguration的自動配置類,把需要的配置都放到這個類里面配置好。最后把這個自動配置類加到META-INF/spring.factories中就行了,是不是很容易,嘻嘻。
demo其實也是使用的之前分析源碼那個工程,下面有地址。重點來配置和啟動一下我們自己的starter。
這里是示例工程demo.
有了starter之后,使用mvn clean install命令將其jar安裝到本地。
在demo工程中引入這個依賴。
<dependency> <groupId>com.wt.starter</groupId> <artifactId>spring-boot-myaop-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
我們starter里面有個MyConfig的配置對吧,好了,現在我們可以在yml或者properties文件中來定義了。我這里用的是yml哈。
myconfig: job: programer user: username: wt age: 25 sex: real_man
注意我們的前綴是myconfig,下面的job和user都是實體類MyConfig的屬性,因為user是個實體了類,因此下面也列出了它的屬性username,age,sex.(可以去前面的MyConfig和UserConfig兩個實體的屬性進行對比)。
starter中除了上面的MyConfig之外,還有個aop監控參數的功能,我們馬上把它用起來。
先定義一個service,接口就不貼了
@Service public class MyStarterServiceImpl implements MyStarterService { @Override @MyAopAnnotation(argTypes = {String.class}) public void helloStarter(String msg, Long currentTime) { System.out.println("----hello starter,msg = " + msg + ",currentTime = " + currentTime); } }
方法加上了注解MyAopAnnotation,為了被starter當中的aop攔截到。
再來定義一個controller用來測試。
@RestController @RequestMapping("/starter") public class MyStarterController { @Autowired private MyConfigService myConfigService; @Autowired private MyStarterService myStarterService; @RequestMapping("/test") public Object starter() { myConfigService.printMyConfig(); myStarterService.helloStarter("wt", System.currentTimeMillis()); return "success"; } }
注意區分一下,MyConfigService是我們starter里面的,MyStarterService是我們demo工程里面的。
現在啟動工程,訪問http://127.0.0.1:8080/starter/test試試!
來看看輸出(復制了輸出,沒有使用截圖):
MyConfig{user=UserConfig{username='wt', age=25, sex='real_man'}, job='programer'} ------------------myaop-starter args monitor start-------------------- type:class java.lang.String<--->arg:wt ------------------myaop-starter args monitor end-------------------- ----hello starter,msg = wt,currentTime = 1564472340205
第一行是 myConfigService.printMyConfig()的輸出,他輸出了我們的在yml中的配置,這個輸出說明了我們的配置被成功賦值給MyConfig了。說明我們的config生效了。
第二行和第四行是starter當中aop部分@Before方法的前后輸出,中間第三行輸出了參數類型String和參數的值wt,因為我們注解上只指定了一個String.class,因此在這里沒有把第二個參數也輸出來,具體邏輯就去看starter當中aop的那個@Before的方法了。
最后一行是被加強的方法的輸出,打印了msg和currentTime。
現在可以來想象一下springboot在yml或properties文件中的Datasource等配置咯!
看到這里starter部分就算結束了
看完上述內容,你們掌握如何自定義springboot starter的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。