功能需求

  1. 提供一个公共的jar包给其他业务模块依赖,需要在这个公共的jar中暴露一个restful API

  2. 采用spring auto config机制,在公共jar包中定义spring.factories文件,将jar包需要注入到spring容器中的bean定义好,业务模块依赖后直接使用,不需要额外定义bean,也不需要指定ComponentScan

之前做法:根据spring文档给的方案调用RequestMappingHandlerMapping的registerMapping方法手动注册一个mapping,可以不使用@Controller注解就可以追加一个rest 接口,可是spring 5之后,spring推出了spring web flux,而RequestMappingHandlerMapping也分成了是spring webmvc版和spring webflux两个,我们给定的jar又不能限定业务模块使用spring web还是spring web flux开发,所以这种方式就不适用了。

解决方式

我们知道,无论是webmvc还是webflux中的RequestMappingHandlerMapping类,都是在afterPropertiesSet方法中查找所有带有Controller或者RequestMapping注解的类,再把对应类中的带有RequestMapping注解的方法解析后注册到对应的RequestMappingHandlerMapping中的,其中判断一个类是否带有@Controller或@RequestMapping的方法如下

@Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

对应的AnnotatedElementUtils.hasAnnotation方法,最终会调用到AnnotatedElementUtils.searchWithFindSemantics方法,代码片段如下

  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;
}
}
}
}

发现这个地方查找是否有指定注解时,如果继承的类或实现的接口有相应的注解也是可以的,利用这个特性,我们可以采用如下思路来实现。

  1. 定义一个标记Controller,里面什么方法也没有,仅仅追加了一个注解

    @RestController
    public class MarkController { }
  2. 定义具体的Controller继承这个标记类,注意这个类不需要用RestController注解

public class HelloController extends MarkController {

	@RequestMapping("/hello")
public String hello() {
return "hello";
}

}


3. 在一个Configuration类中用@Bean注解声明这个类 ```
@Configuration
public class BeanConfig { @Bean
public HelloController helloController() {
return new HelloController();
} } ``` 这样我们就可以通过@Bean的形式声明Controller,之后把这个BeanConfig直接追加到spring.factories中,其他模块依赖这个jar之后,自动就会有一个/hello的接口了。

spring boot通过@Bean注解定义一个Controller的更多相关文章

  1. Spring Boot 二十个注解

    Spring Boot 二十个注解 占据无力拥有的东西是一种悲哀. Cold on the outside passionate on the insede. 背景:Spring Boot 注解的强大 ...

  2. spring boot 中@Autowired注解无法自动注入的错误

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/huihuilovei/article/de ...

  3. Spring Boot中@Scheduled注解的使用方法

    Spring Boot中@Scheduled注解的使用方法 一.定时任务注解为@Scheduled,使用方式举例如下 //定义一个按时间执行的定时任务,在每天16:00执行一次. @Scheduled ...

  4. spring boot @ConditionalOnxxx相关注解总结

    Spring boot @ConditionalOnxxx相关注解总结 下面来介绍如何使用@Condition public class TestCondition implements Condit ...

  5. Spring boot 使用的注解有哪些?

    Spring boot 使用的注解有哪些? 注解 作用 @SpringBootApplication 等价于 @Configuration + @EnableAutoConfiguration + @ ...

  6. (32)Spring Boot使用@SpringBootApplication注解,从零开始学Spring Boot

    [来也匆匆,去也匆匆,在此留下您的脚印吧,转发点赞评论] 如果看了我之前的文章,这个节你就可以忽略了,这个是针对一些刚入门的选手存在的困惑进行写的一篇文章. 很多Spring Boot开发者总是使用 ...

  7. Spring Boot 计划任务中的一个“坑”

    计划任务功能在应用程序及其常见,使用Spring Boot的@Scheduled 注解可以很方便的定义一个计划任务.然而在实际开发过程当中还应该注意它的计划任务默认是放在容量为1个线程的线程池中执行, ...

  8. spring boot开发,jar包一个一个来启动太麻烦了,写一个bat文件一键启动

    spring boot开发,jar包一个一个来启动太麻烦了,写一个bat文件一键启动 @echo offcd D:\workProject\bushustart cmd /c "title ...

  9. Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?

    启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解: @SpringBootConfiguration:组合了 ...

随机推荐

  1. tp5 select出来数据集(对象)转成数组

    1.先在数据库配置文件中 //数据集返回类型 'resultset_type' => 'collection', 2.在使用时, 使用 toArray() 方法 //查询数据库 $news = ...

  2. Django入门4--admin

    python3选择__str__(self),python2选择__unicode__(self):

  3. Spring Cloud探路(二) Erueka客户端的建立

    接上篇 1.pom.xml与上篇一致 2.新建包及Application启动类 @Configuration @ComponentScan @EnableEurekaClient @EnableAut ...

  4. P1099 双连击

    题目描述 我们假设一个二位整数 \(N(10 \le N \le 99)\) ,它的十位上的数字是 \(A\) ,个位上的数字是 \(B\) ,如果 \(A\) 和 \(B\) 的比例关系满足 \(A ...

  5. win10 uwp 使用 Azure DevOps 自动构建

    通过 Azure DevOps 可以做到自动构建程序,覆盖计划.创建.编程.测试.部署.发布.托管.共享等各个环节,适用于大多数的语言.平台. 本文继续使用图床为例告诉大家如何使用 Azure Dev ...

  6. H3C 示例:根据子网数划分子网

  7. H3C设置下次启动的配置文件

  8. fetch是什么?写一个fetch请求

    fetch是web提供的一个可以获取异步资源的api,目前还没有被所有浏览器支持,它提供的api返回的是Promise对象,所以你在了解这个api前首先得了解Promise的用法. 参考链接:http ...

  9. React Mobile 搭建记录

    __dirname 总是指向被执行 js 文件的绝对路径,./ 会返回你执行 node 命令的路径,例如你的工作路径. path.join()方法可以连接任意多个路径字符串.要连接的多个路径可做为参数 ...

  10. 【25.93%】【676D】Theseus and labyrinth

    time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...