Spring的依赖注入是否会破坏信息隐藏?

时间:2009-03-09 20:06:38

标签: java spring dependency-injection encapsulation

来自C ++背景我必须掌握Java的复杂性 世界及其框架。看看DI的弹簧框架我 发现很难相信我必须制作每个setter函数 这将是DI公众的主题。不是那个要求打破了 信息隐藏原则?

当然我希望春天能够设置我的私人部分 类,但我当然不希望每个客户端类都能够做到 同样的。

我在这里缺少什么?

10 个答案:

答案 0 :(得分:15)

我同意你的观点 - 这就是我更喜欢构造函数注入的原因。

答案 1 :(得分:6)

如果你接口的代码,你只需要在实现上公开setter。当您将接口注入系统的其他部分时,它们无法访问实现细节或对象的状态。

答案 2 :(得分:5)

你(可能)必须制作一个制定者,它会向你的外部通知你的一些内部细节,但是没有必要制作一个吸气剂。所以你要揭示一些信息,但不是真的太多;除了预期目的之外,它对任何事情都没有用。

此外,我建议使用注释和@Autowired,在这种情况下,您不需要制作公共设置器。

答案 3 :(得分:3)

如果使用spring注释(@Autowired),您可以使用DI私人成员。

如果你在我的视图中选择松耦合和(单位)可测试弹簧DI会打破不应隐藏的信息。

答案 4 :(得分:1)

我在这里有基本相同的问题:

Encapsulation in the age of frameworks

我认为答案可能是构造函数注入。用setter公开你的属性使得很难对任何东西进行封装并保持良好的对象状态。

答案 5 :(得分:1)

从未使用@Autowired,我倾向于喜欢在构造函数中使用参数,但有时很难理解参数的含义,特别是如果你有很多参数 - 在这种情况下,我更喜欢使用“Builder”方法在Effective Java中描述。构造函数接收构建对象(具有setter),并使用它构造自身。类的注入属性是final(immutability),“Builder”类包含setter但不包含getter(它不需要我们将它声明为正在构造的类的内部类),并且不需要setter仅为Spring创建:

<bean id="runnable" class="MyClass">
   <constructor-arg>
     <bean class="MyClass$Builder">
       <property name="p1" value="p1Value"/>
       <property name="p2" value="p2Value"/>
       <property name="p3" value="p3Value"/>
       <property name="p4" value="p4Value"/>
     </bean>
   </constructor-arg>
</bean>

班级代码:

public class MyClass {
   private final String p1;
   private final String p2;
   private final String p3;
   private final String p4;
   public MyClass(Builder builder) {
      this.p1 = builder.p1;
      this.p2 = builder.p2;
      this.p3 = builder.p3;
      this.p4 = builder.p4;
   }

   ...

   public static class Builder {
      private String p1;
      private String p2;
      private String p3;
      private String p4;
      public void setP1(String p1) {
         this.p1 = p1;
      }
      ... and so on
   }
}

答案 6 :(得分:0)

我认为这是一种权衡。您可以减少硬连线依赖性,但是您可能会暴露实现的内容。使用正确的抽象,您也可以减少它,但随后增加代码库的复杂性(例如,具有可以是LDAP连接或SQL连接的通用“连接”)。

就个人而言,我认为使用构造函数注入也不会对它有帮助,因为它更具概念性。

我必须查看@Autowire,tho'。

TJ

答案 7 :(得分:0)

只是想提一下,我(无意中)发布了这个问题的更通用版本,并对此问题有了进一步的见解:Must Dependency Injection come at the expense of Encapsulation?

答案 8 :(得分:0)

不同意Spring打破封装的观点。即使你有pojo你已经获得并在课堂上暴露并且第三方消耗你的jar,仍然有可能jar的使用者做同样的事情,这可能是Spring bean配置。 (对于任何其他OOP语言都是如此)

Spring只提供了可以通过代码完成的方法,并且该控件移出了代码(IOC)。

Consumer(考虑其他程序员使用你的库),通过spring配置创建bean,你的代码仍然可以控制。没有正文阻止你验证用户给出的输入(spring IOC框架也会通过setter中的其他类调用你的setter来完成相同的代码)。

public void setAge(int age) {
 if ( age < 0 ) {
   throw new AppException("invalid age!");
 }
 this.age=age;
}

答案 9 :(得分:0)

这是我更喜欢Guice的另一个原因;)Guice和Spring都实现了JSR 330 DI规范,但是使用Guice我可以注入我的私有实例字段而没有setter,我真的不喜欢构造函数注入,因为它似乎更难重构。在我的拙见中,这也只是更多的打字而没有多少价值。

后, 迪安