【问题标题】:UnderStanding of @Controller @Service @Repository@Controller @Service @Repository 的理解
【发布时间】:2017-01-21 13:32:39
【问题描述】:

我对依赖注入有疑问,假设我的控制器、服务、dao 都是单例的,所以通常当我们创建控制器时,我们将服务作为该类的实例变量注入,但如果我们的控制器是单例模式,则根据stateless 那么只有我们不会遇到任何并发问题,但是在这里我们声明了服务依赖关系,所以它不应该是无状态的,所以我们必须注意同步?

由于我是初学者,请清除这个疑问,所以我希望很自然地有这个疑问,我不知道我是否完全错误地思考。请帮助。

【问题讨论】:

  • 你认为你需要什么同步?
  • 我只想知道,如果我是控制器类中的注入服务 bean,它本质上是单例的,那么这样做是不是让控制器本质上是有状态的?如果我这样做,我是否没有做错任何事情,因为到处都提到任何单例 bean 都应该是无状态的以防止并发。
  • 为什么你认为服务不应该是无状态的?所有单例 bean 都应该是无状态的(线程安全的)
  • 是的,你是对的,所有的单例 bean 都应该是无状态的,如果不是,那么不同的线程将共享相同的数据并导致问题。我发现了清晰的内存模型和了解 jvm 内存模型的好处,通过学习这个我可以做更好的设计。谢谢 :)

标签: spring spring-mvc


【解决方案1】:

这就是为什么在声明依赖服务时需要使用@Autowired。有效地将初始化过程交给 Spring 框架,而不是自己实例化。由于 Spring 只有无状态 bean,因此您将一个无状态单例注入另一个无状态单例,因此无需手动管理线程。

【讨论】:

    【解决方案2】:

    Spring 中的所有 bean 默认都是单例的。这包括任何@Controller@Service@Repository 等,以及任何 xml 定义的 bean。

    您可以阅读thisthis

    来自Java basic variable tutorial

    局部变量 类似于对象在字段中存储其状态的方式, 方法通常会将其临时状态存储在局部变量中。这 声明局部变量的语法类似于声明字段 (例如,int count = 0;)。没有特殊的关键字指定 作为局部变量;这一决心完全来自 声明变量的位置——在 方法的打开和关闭大括号。因此,局部变量是 仅对声明它们的方法可见;他们不是 可从班级的其他人访问。

    【讨论】:

    • 谢谢,但据我所知,您的意思是当我的控制器自动封装服务 bean 时,只有当服务也是无状态时它才保持任何状态,因此多个请求只会共享所在类的本地成员在不同请求线程的堆栈中
    • 你说“班级的本地成员”是什么意思?您是否希望您的服务(或任何其他组件)具有任何有状态的内部属性?
    • 对不起,我的错误不是类的本地成员,我的意思是类的方法,它们本质上是公共的及其局部变量
    • 方法类中的任何局部变量都不会在多个方法的执行之间共享,不管每次执行是否同时从不同的线程完成
    • "方法类中的任何局部变量都不会在多个方法的执行之间共享,"你能解释一下吗,我想从头到尾看清楚。
    【解决方案3】:

    如果你的服务和控制器是无状态的,可以相互注入。

    您不应该在这些类中声明任何保持状态的变量。 final 变量没问题。

    如果所有操作都在方法中定义并且它们不使用类的任何变量,那么您正在执行的依赖注入是完全安全的。

    【讨论】:

    猜你喜欢
    • 2020-05-07
    • 2023-02-02
    • 2011-01-06
    • 1970-01-01
    • 2013-03-09
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多