【问题标题】:Is the Class with @Controller annotation a single object?带有@Controller 注释的类是单个对象吗?
【发布时间】:2018-07-26 11:21:19
【问题描述】:

我知道两个具有相同内容的请求使用不同的线程。而且我认为不同的线程会使用@Controller 注解创建不同的实例。但是当我运行下面的代码时,我发现我的想法是错误的。

测试代码:

@Controller
@RequestMapping("test")
public class TestADEDSAController {
    private String string = "";

    @RequestMapping("controllerTest")
    @ResponseBody()
    public String controllerTest(@RequestParam String string) {
        return this.string += string;
    }
}

第一次响应内容是这样的:

test

第二次是这样的:

testtest

JVM里好像只有一个Test实例。

我想知道JVM中总是只有一个@Controller实例是不是真的?另外,在哪里可以找到这个过程的详细介绍?

【问题讨论】:

  • @Controller 没有属性scope

标签: java spring spring-mvc tomcat io


【解决方案1】:

默认情况下,Spring 中的所有 bean 都创建为 singleton(每个 IOC 容器一个)。

这是javadoc

(默认)将单个 bean 定义限定为每个 Spring IoC 容器的单个对象实例。

【讨论】:

    【解决方案2】:

    默认情况下,Spring 创建 bean 的单个共享实例。 bean 范围默认为singleton。如果您需要在每个请求上创建一个新实例,您应该将 bean 范围定义为prototype。这可以通过使用 @Scope("prototype") 注释类或通过在 spring 配置 xml 中定义范围来完成,如下所示:

     <bean id="controllerId" class="com.package.name.TestADEDSAController" scope="prototype"/>
    

    请通过https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html 更好地了解spring 的bean scope。

    【讨论】:

    • 谢谢,你的回答很详细。在我阅读了你给我的文档后,我调试了研究这个过程的spring框架源代码,当我调试到Class AbstractUrlHandlerMapping的方法lookupHandler()时,我发现字段handlerMap的大小是6,但我找不到怎么初始化的,让我很困惑。
    【解决方案3】:

    不,默认情况下对象是单例。这意味着您的对象必须是线程安全的。 因此,在控制器中包含不安全的值(如字符串)是一种不好的做法(常量除外)。

    如果两个线程同时进入那里,您的字段可能会损坏。

    【讨论】:

      【解决方案4】:

      默认作用域是“singleton”,所以如果你需要Spring每次创建一个新实例,除了@Controller注解,你还可以使用@Scope("prototype")注解。还有其他网络感知范围,如请求、会话和全局会话。阅读here 了解示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多