【问题标题】:Are annotations applicable to subclasses?注释是否适用于子类?
【发布时间】:2015-10-28 23:33:39
【问题描述】:

我想这个问题已经有一段时间了,但一直没能找到关于这个话题的任何东西。

假设我正在使用 Spring MVC 并定义了一系列 Controllers。

@RestController
public abstract class AbstractController {

    @Resource
    private Environment env;

    ...
    ...
}

对于以下内容,UserController 注册是否需要 @RestController 注释?

@RequestMapping(value = "/user")
public class UserController extends AbstractController {

    @RequestMapping("value = "", method = RequestMethod.GET)
    public ResponseEntity<User> getUser() {
       ...
       return new ResponseEntity<>(user, HttpStatus.OK);
    }          
}

【问题讨论】:

    标签: java spring-mvc inheritance annotations


    【解决方案1】:

    这里有两个问题。 SJuan76 has answered the first,关于类型注解的继承。

    第二个问题

    UserController 注册需要@RestController 注释吗?

    涉及更多一点。

    Spring有一个meta-annotations的概念:

    Spring提供的很多注解都可以作为 您自己的代码中的元注释。元注释只是一个 可以应用于另一个注释的注释。

    [...]

    元注释也可以组合起来创建组合注释。 例如,Spring MVC 中的 @RestController 注释是 由@Controller@ResponseBody组成。

    但是,组件扫描过程不会为 abstract 类生成 bean 定义。更重要的是,它不会发现这些对本身没有注释的子类型的元注释。换句话说,Spring 将跳过您的 UserController 类型并且不会为其注册 bean 定义。 (我敢肯定它可以,只是 4.1.7.RELEASE 没有。)

    现在,如果您确实使用 @Component 注释您的类型 UserController 以强制 Spring 生成 bean 定义,则处理 @ResponseBody 的 Spring MVC 进程将检测到 @RestController 超类型上的 @RestController 注释。

    这是在RequestResponseBodyMethodProcessor 中完成的,它使用AnnotationUtils.findAnnotation 在包含您的处理程序方法的类型上查找注释。它的 javadoc 状态

    在提供的Class 上找到annotationType 中的一个Annotation遍历其接口、注释和超类,如果 给定的类本身不存在注释。

    此方法显式处理类级别的注释,这些注释不是 声明为继承的以及元注释和注释 接口。

    因此,如果你有

    @Component
    @RequestMapping(value = "/user")
    public class UserController extends AbstractController {
    

    Spring 会检测并为UserController 生成一个bean。当使用您的 getUser 处理程序方法处理对 /user 的请求时,Spring MVC 将像您的类实际上使用 @RestController(或 @ResponseBody)注释一样运行。

    但是,在您的情况下,您的处理程序方法返回一个ResponseEntity@ResponseBodyHandlerMethodReturnValueHandler 不处理它,它由 HttpEntityMethodProcessor 处理。


    注意 abstract 类是 @Controller 类型的超类型:如果您有许多子类型也应该是 bean 并且 abstract 超类型包含 @RequestMapping 注释方法,Spring MVC 将无法注册您的处理程序方法,因为它会考虑在它们之间重复该超类型方法。

    【讨论】:

      【解决方案2】:

      如果您决定注释为@Inherited,则可以。在此示例中,@RestController 未使用 @Inherited 元注释定义,因此它不适用于 AbstractController 的子类。

      【讨论】:

      • 建议的增强回答:指定@RestController(或@Controller@Component)可能会导致异常,因为Spring会尝试实例化abstract类。
      • @Andreas 你必须给 Spring 一些信任。它不会做这样的事情。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-25
      • 2019-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多