你可以通过在 Servlet 的 WebApplicationContext 中使用标准的 Spring Bean 定义来定义控制器 Bean。@Controller允许自动检测,与 Spring 对检测 classpath 中的 @Component类并为其自动注册 Bean 定义的一般支持保持一致。它也是注解类的一个 stereotype,表明它是一个 Web 组件。

为了实现对这种 @Controller Bean 的自动检测,你可以在你的 Java 配置中添加组件扫描,如下例所示:

  1. @Configuration
  2. @ComponentScan("org.example.web")
  3. public class WebConfig {
  4. // ...
  5. }

下面的例子显示了前述例子的 XML 等效配置:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xsi:schemaLocation="
  7. http://www.springframework.org/schema/beans
  8. https://www.springframework.org/schema/beans/spring-beans.xsd
  9. http://www.springframework.org/schema/context
  10. https://www.springframework.org/schema/context/spring-context.xsd">
  11. <context:component-scan base-package="org.example.web"/>
  12. <!-- ... -->
  13. </beans>

@RestController 是一个 组合的注解,它本身是由 @Controller 和 @ResponseBody 组成的元注解,表示一个控制器的每个方法都继承了类型级的 @ResponseBody 注解,因此,直接写入响应体,而不是用 HTML 模板进行视图解析和渲染。

AOP 代理

在某些情况下,你可能需要在运行时用 AOP 代理来装饰一个控制器。一个例子是,如果你选择在控制器上直接使用 @Transactional注解。在这种情况下,对于控制器,我们建议使用 基于类的代理。这通常是控制器的默认选择。然而,如果一个控制器必须实现一个不是 Spring Context 回调的接口(如 InitializingBean*Aware等),你可能需要明确配置基于类的代理。例如,对于 <tx:annotation-driven/>,你可以改为<tx:annotation-driven proxy-target-class="true"/>,对于 @EnableTransactionManagement,你可以改为@EnableTransactionManagement(proxyTargetClass = true)