提供一个公共的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的接口了。接口