C++ のバックグラウンドを持つ私は、Java の世界とそのフレームワークの複雑さを習得する必要があります。DIのSpringフレームワークを見ていると、DIの対象となる各セッター関数を公開する必要があるとは信じがたいです。その要件は、情報隠蔽の原則を破っていませんか?
もちろん、Spring でクラスのプライベート パーツを設定できるようにしたいのですが、すべてのクライアント クラスで同じことができるようにしたくはありません。
ここで何が欠けていますか?
C++ のバックグラウンドを持つ私は、Java の世界とそのフレームワークの複雑さを習得する必要があります。DIのSpringフレームワークを見ていると、DIの対象となる各セッター関数を公開する必要があるとは信じがたいです。その要件は、情報隠蔽の原則を破っていませんか?
もちろん、Spring でクラスのプライベート パーツを設定できるようにしたいのですが、すべてのクライアント クラスで同じことができるようにしたくはありません。
ここで何が欠けていますか?
私はあなたの意見に同意します-それが私がコンストラクター注入を好む理由です。
インターフェイスにコーディングする場合は、実装でセッターを公開するだけで済みます。インターフェイスをシステムの他の部分に挿入すると、実装の詳細やオブジェクトの状態にアクセスできなくなります。
内部の詳細の一部を外部に通知するセッターを作成する必要がある場合がありますが、ゲッターを作成する必要はありません。したがって、いくつかの情報を明らかにしていますが、それほど多くはありません。本来の目的以外には何の役にも立ちません。
さらに、アノテーションと @Autowired を使用することをお勧めします。この場合、パブリック セッターを作成する必要はありません。
スプリング アノテーション (@Autowired) を使用すると、プライベート メンバーを DI できます。
私の見解では、疎結合と (単体) テスト可能性を求めると、DI によって、隠してはならない情報が明らかになります。
@Autowired を使用したことはありません。コンストラクターでパラメーターを使用するのが好きな傾向がありますが、パラメーターの意味を理解するのが難しい場合があります。特に、パラメーターが多数ある場合はそうです。その場合は、Effective で説明されている「ビルダー」アプローチを使用することを好みます。ジャバ。コンストラクターはビルド オブジェクト (セッターを含む) を受け取り、それを使用して自身を構築します。クラスの注入された属性は final (不変) であり、「Builder」クラスにはセッターが含まれていますが、ゲッターは含まれていません (構築中のクラスの内部クラスとして宣言するので必要ありません)、セッターは必要ありません。春のためだけに作成する:
<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
}
}
私が(うっかりして)この質問のより一般的なバージョンを投稿したこと、およびこの問題についてさらに洞察があることを言及したかっただけです。
それが私が Guice を好むもう 1 つの理由です ;) Guice と Spring はどちらも JSR 330 DI 仕様を実装していますが、Guice を使用すると、セッターなしでプライベート インスタンス フィールドに注入できます。また、私の謙虚な意見では、あまり価値がないために、より多くのタイピングが行われます。
後、ディーン
Spring break カプセル化という点には同意しません。get と set がクラスで公開されている pojo があり、サード パーティが jar を消費する場合でも、jar の消費者が Spring Bean 構成で可能な同じことを行う可能性があります。(他の OOPs 言語にも当てはまります)
Spring は、コードを介して実行できる方法を提供し、そのコントロールをコードの外に移動しました (IOC)。
コンシューマー (他のプログラマーがあなたのライブラリーを使用していると考えてください) は、Spring 構成を介して Bean を作成しますが、それでもコードは制御できます。セッターでユーザーから与えられた入力を検証するのを止める人はいません(Spring IOCフレームワークも、セッターを呼び出す他のクラスによって行われるのと同じコードを通過します)。
public void setAge(int age) {
if ( age < 0 ) {
throw new AppException("invalid age!");
}
this.age=age;
}