spring boot通过@Bean注解定义一个Controller

本文内容纲要:spring boot通过@Bean注解定义一个Controller

功能需求

  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

原文链接:https://www.cnblogs.com/gaofeng-henu/p/12168789.html

以上是 spring boot通过@Bean注解定义一个Controller 的全部内容, 来源链接: utcz.com/z/362340.html

回到顶部