2016-08-27 10 views
0

コンテキスト春 - Builderのパターン

春4.1.7を利用するアプリケーションを使用して豆の注入。すべての設定はXMLファイル(注釈を使用しない)になっていますが、私はそのように保ちます(しかし、私がしなければならないことをやり遂げる方法を変えることができます)。私はビルダークラスが付属して新しいクラスを作成している

問題

今、この新しいクラスに他のBeanを挿入したいと思います。おそらく、それを行うためにlookupメソッドや同様のソリューションを使用して、呼び出し側Beanで新しいクラスのBuilderを使用してインスタンスを作成することができます。しかし、私はむしろ、この新しいクラスのインスタンスを呼び出し元Beanに注入し、ビルダを使用して作成します。これが私がそれをどうやって行うことができないのか分かりません。たとえば、これは抽象ファクトリーのように見えますが、実行時に抽象ファクトリにパラメータを渡すことはできません(ビルダーに渡されます)。

質問より明確にするためにいくつかのコードスニペット:

public final class Processor { 

    private final StatusEnum newStatus; 
    private final Long timeOut; 

    // I'd like this to be be injected by Spring through its setter (below) 
    private DaoBean daoInstance; 

    private Processor() { 
     this.newStatus = null; 
     this.timeOut = null; 
    } 

    private Processor(Builder builder) { 
     this.newStatus = builder.getNewStatus(); 
     this.timeOut = builder.getTimeOut(); 
    } 

    // To be called by Spring 
    public void setDaoInstance(DaoBean instance) { 
     this.daoInstance = instance; 
    } 

    public void updateDatabase() { 
     daoInstance.update(newStatus, timeOut); 
    } 

    // Builder class 
    public static final class Builder { 
     private StatusEnum newStatus; 
     private Long timeOut; 
     // lots of other fields 

     public Long getTimeOut() { 
      return this.timeOut; 
     } 

     public StatusEnum getNewStatus() { 
      return this.newStatus; 
     } 

     public Builder withTimeOut(Long timeOut) { 
      this.timeOut = timeOut; 
      return this; 
     } 

     public Builder withNewStatus(StatusEnum newStatus) { 
      this.newStatus = newStatus; 
      return this; 
     } 

     public Processor build() { 
      return new Processor(this); 
     } 
    } 
} 

を私は「プロセッサ」クラスに注入される「DaoBean」のインスタンスをしたいと思います。しかし、そうするためには、プロセッサーはBeanでなければならないか、そうでなければlookupメソッドのようなものを利用しなければなりません。私はプロセッサの春は維持しつつ、その発信者に注入することができBeanを作ることができる場合、私は疑問に思う、この代わりの

new Processor.Builder() 
    .withTimeOut(1000L) 
    .withNewStatus(StatusEnum.UPDATED) 
    .build() 
    .updateDatabase(); 

:私はプロセッサを使用したいところはどこでも一方で、私はこのような何かをしなければなりませんその不変性。 DaoBeanのインスタンスは、Springによってプロセッサに注入できます。そうすれば、配線コードとビジネスロジックを分離することができます。

ビルダーには2つ以上のフィールドがあり、それらのすべてを設定する必要はありません。これが、私が抽象的な工場が行く方法であると考えた理由です(プロセッサのインスタンスをさまざまな方法で構築する)。

+0

申し訳ありませんが、私はまだあなたの実際の問題が何かを理解していません。いくつかのコードを投稿してください。例えばそのクラス?そうすれば、あなたはあなたが持っているものとあなたが望むものをよりよく理解するでしょう... –

+0

質問が更新されました。 –

答えて

0

一つの解決策、ビルダーを維持しながら、おそらく単にビルダー自体のSpring Bean ...

これは、このようなことを可能にすることことであろう。..

@Autowired 
private Builder builder; 

public void someMethod() { 
    Result = builder.withX(...).doSomething(); 
} 

この方法で、あなたの結果オブジェクトは不変ですが、素敵なビルダーを使って作成することができ、ビルダーはSpring bean(あなたの場合はdao)をそこにあることに気づいていなくても注入できます。

そして、あなたはビルダーを自分で作成しますが、春はあなたのためにそれを作成させないこと、である変更だけの事... JavaConfigまたはXMLの設定と

@Component 
@Scope("prototype") // normally a good idea 
public static class Builder { 
    @Autowired 
    private DaoBean dao; 

    // your logic here 
} 

(同じ作品、あなたの場合スキャンする必要はありません)。

特に、多くの組み合わせでは、工場には複雑なメソッドシグネチャが必要なため、ビルダーパターンが好まれます。もちろん、ビルダーには、属性タイプの特定の組み合わせが少なくとも理論的に許容可能であるかどうかをコンパイル時にチェックすることができないという欠点があります。さて、あなたは様々なビルダーとそれをシミュレートすることができますが、それはおそらく過剰なものでしょう。

+0

ありがとうございます。プロセッサーの依存関係(DaoBeanなど)で何を提案しますか?また、私はあなたが「ビルダーには欠点があります」という意味を理解していませんでした。私は通常、ビルド関数のパラメータを検証します。 –

+0

プロセッサの依存関係。 DaoBeanはSpringによってBuilderに注入され、その後Builderによってプロセッサに渡されます。 (私は、ビルダー自体をとる(潜在的にプライベートな)コンストラクターを作成する傾向があるため、コンストラクターの複雑な署名や隠されたセッターメソッドが不要です。そして、私は、署名だけで(コンパイル時に)文字列、文字列、intまたは文字列、intまたはちょうどintのいずれかを選択することができないので、すべてのチェックは実行時に行わなければならない(しかしそれはTDDの非常に小さな欠点です)。 –

+0

ありがとうございます。これが行われます。 –

関連する問題