提供一個公共的jar包給其餘業務模塊依賴,須要在這個公共的jar中暴露一個restful APIweb
採用spring auto config機制,在公共jar包中定義spring.factories文件,將jar包須要注入到spring容器中的bean定義好,業務模塊依賴後直接使用,不須要額外定義bean,也不須要指定ComponentScanspring
以前作法:根據spring文檔給的方案調用RequestMappingHandlerMapping的registerMapping方法手動註冊一個mapping,能夠不使用@Controller註解就能夠追加一個rest 接口,但是spring 5以後,spring推出了spring web flux,而RequestMappingHandlerMapping也分紅了是spring webmvc版和spring webflux兩個,咱們給定的jar又不能限定業務模塊使用spring web仍是spring web flux開發,因此這種方式就不適用了。restful
咱們知道,不管是webmvc仍是webflux中的RequestMappingHandlerMapping類,都是在afterPropertiesSet方法中查找全部帶有Controller或者RequestMapping註解的類,再把對應類中的帶有RequestMapping註解的方法解析後註冊到對應的RequestMappingHandlerMapping中的,其中判斷一個類是否帶有@Controller或@RequestMapping的方法以下mvc
@Override protected boolean isHandler(Class<?> beanType) { return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) || AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class)); }
對應的AnnotatedElementUtils.hasAnnotation方法,最終會調用到AnnotatedElementUtils.searchWithFindSemantics方法,代碼片斷以下app
else if (element instanceof Class) { Class<?> clazz = (Class<?>) element; if (!Annotation.class.isAssignableFrom(clazz)) { // Search on interfaces 在實現接口中查找 for (Class<?> ifc : clazz.getInterfaces()) { T result = searchWithFindSemantics(ifc, annotationTypes, annotationName, containerType, processor, visited, metaDepth); if (result != null) { return result; } } // Search on superclass 在父類中查找 Class<?> superclass = clazz.getSuperclass(); if (superclass != null && superclass != Object.class) { T result = searchWithFindSemantics(superclass, annotationTypes, annotationName, containerType, processor, visited, metaDepth); if (result != null) { return result; } } } }
發現這個地方查找是否有指定註解時,若是繼承的類或實現的接口有相應的註解也是能夠的,利用這個特性,咱們能夠採用以下思路來實現。ide
定義一個標記Controller,裏面什麼方法也沒有,僅僅追加了一個註解rest
@RestController public class MarkController { }
定義具體的Controller繼承這個標記類,注意這個類不須要用RestController註解code
public class HelloController extends MarkController { @RequestMapping("/hello") public String hello() { return "hello"; } }
在一個Configuration類中用@Bean註解聲明這個類繼承
@Configuration public class BeanConfig { @Bean public HelloController helloController() { return new HelloController(); } }
這樣咱們就能夠經過@Bean的形式聲明Controller,以後把這個BeanConfig直接追加到spring.factories中,其餘模塊依賴這個jar以後,自動就會有一個/hello的接口了。接口