質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.37%

  • Java

    15109questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Spring

    787questions

    Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

  • Spring Boot

    664questions

    Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

  • DI (Dependence Injection)

    17questions

    DI (Dependence Injection)は、「依存性の注入」という概念を指します。オブジェクト間で依存性のあるコードを外部の設定ファイルから注入するソフトウェアパターン設計思想です。

コンストラクタに引数が必要なクラスのDIについて

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 5,429

msss

score 18

コンストラクタに引数(処理中に値が決定する)が必要なクラスをDIする場合
どのように実装したらよいのでしょうか。

1.基本的にシングルトンなので動的な引数でインスタンス化は出来ないのでしょうか。

2.そのような場合はコンテナ管理させずにnewしてあげるのが一般的なのでしょうか。

@Controller
public class HogeController {
    @Autowired
    private HogeService service;

    void test(){
        int i = 1;
        String s = "test";

// 本当は以下のようなことがしたいのですが、どのようにすれば良いのでしょうか。
        HogeService service = new HogeService(i, s);

        service.print();
    }
}

@Service
public class HogeService {
    final int a;
    final String b;

    HogeService (int a, Sting b){
        this.a = a;
        this.b = b;
    }

    public void print(){
        System.out.println(i);
        System.out.println(s);
    }
}

 追加(解決策?)

  • new()した方が良いような気もしますがコンテナに登録されたオブジェクトにコンストラクタに引数が渡せました。
@Controller
public class HogeController {
    void test(){
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
        TestDI hogeA = (TestDI) context.getBean("getHogeInstance", 1, "@@@");
        TestDI hogeB = (TestDI) context.getBean("getHogeInstance", 2, "◆◆");

        hogeA.print();
        hogeB.print();
    }
}

@Service
public class Test {
    @Bean
    @Scope("prototype")
    HogeService getHogeInstance(int i, String s) {
        return new HogeService (i, s);
    }
}

public class HogeService {
    final int a;
    final String b;

    HogeService (int a, Sting b){
        this.a = a;
        this.b = b;
    }

    public void print(){
        System.out.println(i);
        System.out.println(s);
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

サンプル

@Configuration
public class ApplicationConfiguration {

  @Bean
  @Scope("prototype") //As we want to create several beans with different args, right?
  String hello(String name) {
    return "Hello, " + name;
  }
}

//and later in your application

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
String helloCat = (String) context.getBean("hello", "Cat");
String helloDog = (String) context.getBean("hello", "Dog");

APIリンク

上記をマネすれば、引数が渡せるのでは?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/17 15:12

    これは@Autowiredして値を設定するのと何が違うのでしょうか。

    キャンセル

  • 2017/02/17 17:05

    回答ありがとうございます。
    上記の方法を用いてコンテナに登録されたオブジェクトにコンストラクタからnewすることが出来ました。
    これが良い方法かどうかはまた別途質問しようと思います。
    ありがとうございました。

    キャンセル

+1

HogeControllerのインスタンスが生成された時点でコンテナから対象のインスタンスが取得されるため、メソッド中で初期値を設定するのは不可能です。

setterなどで設定してあげるか(immutableでやりたいのであればこの方法は使えません。)
コンテナ管理させないか。

ですかね。とりあえずなんでもかんでもコンテナ管理はやめておいたほうがいいです。
コンテナ管理をさせたい理由と実現したいことのイメージがあれば別にアドバイスが出来るかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/02/17 13:53

    回答ありがとうございます。
    ※コードを少し修正しました(コンストラクタ引数をfinalにしました)

    特にコンテナ管理させたいわけではないです。
    上記の場合はnew()しておくのが一般的という回答でよろしいでしょうか。

    キャンセル

  • 2017/02/17 14:01

    そうですね。一般的なオブジェクトでコンテナ管理させない場合はコンテナ管理させないほうがいいです。
    つまり、new()で取得するのが一般的(一般的かどうかといったら自分はstatic factoryのほうが好きですが)です。
    コンテナ管理する対象はロジックだったり、値をリクエスト間で引き継ぎたいオブジェクトだったりです。
    ちなみに一般的には@Serviceを付与するのはでサービス層のクラス(ビジネスロジック等)です。

    キャンセル

  • 2017/02/17 14:34

    ◇ロジックの処理も、その業務を行うのに必須の前提条件が必要な場合もあると思います。
    そのような場合は全てのメソッドに前提条件の値を渡すことになるのでしょうか。

    ◇ちなみに、7tsuno様はコンテナ管理させる場合とさせない場合をどのように切り分けられているのでしょうか。

    キャンセル

  • 2017/02/17 17:54

    ◇ロジックの処理も、その業務を行うのに必須の前提条件が必要な場合もあると思います。
    ロジックにフィールドを持たせたいということでしょうか。基本的にはコンテナ管理されたロジックにフィールドを持たせるのは危険です。(スコープにもよりますが他のスレッドやリクエストに値が変更される可能性があるため。)
    全てのメソッドに前提条件の値を渡すことになると思います。

    ◇コンテナ管理させる場合とさせない場合
    設計にもよりますが、Controller, Helper, Service,Form, DTOを使うような場合、
    https://terasolunaorg.github.io/guideline/public_review/Overview/ApplicationLayering.html
    Controller, Helper, Serviceはフィールドを持たないがコンテナ管理。
    Form, DTOはnewで取得
    という風に切り分けますね。

    キャンセル

  • 2017/02/17 17:57

    追加で、1セッションで共通で扱いたいオブジェクトや1アプリケーションで共通で扱いたいオブジェクトがあればコンテナ管理させます。
    件のようなオブジェクトはすぐに生存期間を終わらせていいものなのでコンテナ管理はさせません。

    キャンセル

  • 2017/02/20 18:02

    とても分かりやすい回答ですっきりしました。
    ありがとうございます!

    キャンセル

同じタグがついた質問を見る

  • Java

    15109questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Spring

    787questions

    Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

  • Spring Boot

    664questions

    Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

  • DI (Dependence Injection)

    17questions

    DI (Dependence Injection)は、「依存性の注入」という概念を指します。オブジェクト間で依存性のあるコードを外部の設定ファイルから注入するソフトウェアパターン設計思想です。