【问题标题】:Service layer in spring - autowire all servicesSpring中的服务层-自动装配所有服务
【发布时间】:2013-08-22 02:56:47
【问题描述】:

我正在考虑我的一些服务。 其中一些看起来像这样:

@Service
public class UserService {

   @Autowired
   UserDao dao;

   @Autowired 
   OtherService1 serv1;
   @Autowired 
   OtherService2 serv2;
   @Autowired 
   OtherService3 serv3;
   ....



}

我在想.. 如果这种将其他服务自动装配成单个服务的概念很普遍,为什么不创建一个“主服务”:

@Service
public class MasterService {


   @Autowired 
   OtherService1 serv1;
   @Autowired 
   OtherService2 serv2;
   @Autowired 
   OtherService3 serv3;
   ...
   @Autowired 
   LastService servN;


}

并将此服务自动装配到所有服务中。

@Service
public class AnyService {

   @Autowired 
   MasterService masterSevice;
}

这样我们每个服务就不会有很多服务,而只有一个来统治所有服务..

提出两个问题:

1) 由于 masterService 包含所有服务,因此我们有一个注入循环。我们能解决吗?

2) 如果问题 1 的答案是“是” - 这是“masterService”的好习惯吗?

【问题讨论】:

    标签: spring service autowired service-layer


    【解决方案1】:

    1) Spring 能够在很多情况下处理依赖循环,尤其是在不使用构造函数注入的情况下。

    2) 尽管如此。你应该绝对避免这种设计。它打破了良好架构的许多原则:

    • 组件应该只能根据需要访问尽可能少的其他组件。 Demeter's Law
    • 关注点分离。服务不应同时处理业务逻辑和表示。
    • 抽象级别。服务不应同时处理数据的逻辑视图和持久性视图。

    违反这些原则可能会导致不良情况,例如:

    • 无法遵循代码路径(单个请求将按照难以理解的顺序通过 12 个服务,并且依赖于许多级别的条件逻辑)。
    • 很难知道哪些组件相互依赖。
    • 强耦合代码(更改低级服务将导致高级服务更改)。

    您从这样的设计中获得的好处非常小(您只是避免了几个@Autowired 注释),不值得冒险。

    【讨论】:

      【解决方案2】:

      我以前没有遇到过这种模式(一个服务包含其他服务)。 我经常看到和使用的如下 -

      *SpecificController1 --> SpecificService1 --> SpecificDao1

      SpecificController2 --> SpecificService2 --> SpecificDao2

      现在,如果 SpecificService1 需要 SpecificService2 中已有的某些功能,那么它只会引用 SpecificService2

      所以,我对上述模式有几个问题:

      1. 如何使用 MasterService?即,任何需要任何服务的控制器(或任何人)都将首先使用 MasterService 来获取对实际服务的引用,或者 MasterService 将充当委托?
      2. 在什么场景下,你需要这样的设计,有什么优势?

      【讨论】:

      • 1.参考,(公共接口) 2. 优点是所有公共服务都可从任何服务获得,并且无需在每个服务中自动装配大量服务。此外,当您使用 xml 时,优势会更大
      【解决方案3】:

      1) MasterService 不一定包含循环。如果是这样,那么你会遇到问题,而且一开始就不在循环中构造你的 bean 要简单得多。

      2) 如果您要注入大量寿命较短的 bean,这可能会很有效,但这种方法的缺点是,任何干预 MasterService 实例的人都可能搞砸其他 bean 的服务.您可以将其隐藏在 getter 方法后面,但将所有内容混为一谈通常不会带来太多好处。

      相反,通常最好将相关服务组合在一起,可能是OtherService1OtherService2,并将它们放在一个界面上。这使得模拟测试变得更加容易,并将相关概念放在一起(最好在它们自己的 jars/模块中)。

      【讨论】:

        【解决方案4】:
        1. 为什么会有循环依赖?有一个服务包含所有其他服务,没有其他服务包含它。话虽如此,循环依赖可以通过将依赖设置为属性而不是构造函数参数来轻松解决。

        2. 我不这么认为,声明一种层次结构(例如在端点中)是一种很好的模式,但是这种方式的优点是什么?您也可以自动装配您想要的每项服务。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-04-29
          • 1970-01-01
          • 2018-05-06
          • 2020-10-05
          • 2015-03-29
          • 1970-01-01
          • 2015-03-03
          • 2016-10-26
          相关资源
          最近更新 更多