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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Spring MVC

Spring MVCとは、Javaを用いてWebアプリケーションを開発できるフレームワーク。アーキテクチャにMVCを採用しており、画面遷移と入出力パラメータの受け渡しの基本的な機能の他、ユーザーの送信したパラメータに対する入力チェックなどさまざまな機能を持ちます。

Java

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

Spring Boot

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

Q&A

解決済

2回答

8784閲覧

Spring Bootでコンストラクタの引数に文字列を受け渡したい

manudon

総合スコア1

Spring MVC

Spring MVCとは、Javaを用いてWebアプリケーションを開発できるフレームワーク。アーキテクチャにMVCを採用しており、画面遷移と入出力パラメータの受け渡しの基本的な機能の他、ユーザーの送信したパラメータに対する入力チェックなどさまざまな機能を持ちます。

Java

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

Spring Boot

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

0グッド

0クリップ

投稿2021/07/27 11:47

前提・実現したいこと

Springbootの練習で生徒の名前を検索するシステムを作っています

RepositoryクラスはCSVファイルからデータを読込、検索
ServiceクラスはRepositoryクラスから生徒番号と生徒名を受け取っています

以前は以下の検索メソッドにCSVファイルのディレクトリを直貼りしていましたが、
Repositoryクラスで作ったコンストラクタで引数を用意し、そちらにディレクトリの文字列を受け渡そうと考えています。

どのように修正すればいいでしょうか?

発生している問題・エラーメッセージ

Parameter 0 of constructor in com.example.demo.StudentRepositoryImpl required a bean of type 'java.lang.String' that could not be found.
Consider defining a bean of type 'java.lang.String' in your configuration.

該当のソースコード

java

1 2@Repository 3public class StudentRepositoryImpl implements StudentRepository { 4 private String dataName; 5 public StudentRepositoryImpl(String str) { 6 dataName = str; 7 } 8 // 検索メソッド 9 @Override 10 public Student searchNo(String studentNo) throws Exception { 11 // このメソッドでdataNameを使用 12 }

java

1ソースコード 2@Service 3public class StudentServiceImpl implements StudentService { 4 5 private final StudentRepository studentRepository; 6 7 public StudentServiceImpl(StudentRepository studentRepository) { 8 this.studentRepository = studentRepository; 9 } 10 11 @Override 12 public String findNo(String number) throws Exception { 13 try { 14 Student student = studentRepository.searchNo(number); 15 return student.getName(); 16 } 17 catch (Exception e) { 18 throw e; 19 } 20 } 21} 22

試したこと

下記のように記述しましたが、実行するとエラーが発生し、実現しません。

java

1StudentRepository studentRepository = new StudentRepositoryImpl("C:/mydata/StudentName.csv");

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ファイルパスの値が Bean 登録されていないため、
@Repository のついた StudentRepositoryImpl をBean登録できずにエラーになっています。

解決策としては以下のどちらかになるかと思います。

  • 設定ファイルに値を書いて、@Value から取得する
  • 設定ファイルの値を @ConfigurationProperties で class にバインドして、その値を使う

例えば、設定ファイルに resources/application.yaml に以下のように書いて

yaml

1app: 2 sample: 3 csv-file: "C:/mydata/StudentName.csv" 4

RepositoryImpl の実装を以下にすると、設定ファイルに書いたファイルパスを読み込めます

Java

1@Repository 2public class StudentRepositoryImpl implements StudentRepository { 3 private final String dataName; 4 public StudentRepositoryImpl(@Value("${app.sample.csv-file}") String str) { 5 dataName = str; 6 } 7// 以下省略... 8}

クラスにバインドしたい場合、以下の手順で追加できます
org.springframework.boot:spring-boot-configuration-processor をビルドツールの設定に追加する。
SpringBoot の Application class に @ConfigurationPropertiesScan を付与する。
適当に設定ファイルに設定と、SpringBoot のスコープ内のどこかに class を作成する。
例としては以下

  • 設定ファイル(resources/application.yaml

yaml

1app: 2 config: 3 csv-file: "hogehoge" 4 timeout: 10 5
  • 設定クラス

Java

1@Getter 2@ConstructorBinding 3@ConfigurationProperties("app.config") 4public class SampleConfig { 5 private final String csvFile; 6 private final int timeout; 7 8 public SampleConfig(String csvFile, int timeout) { 9 this.csvFile= csvFile; 10 this.timeout = timeout; 11 } 12}

このクラスがBean登録されるので、これを引数から渡すことができる

Java

1@Repository 2public class ConfigRepositoryImpl implements StudentRepository { 3 private final String cfvFilePath; 4 private final int timeout; 5 public ConfigRepositoryImpl(SampleConfig config) { 6 cfvFilePath = config.getCsvFile(); 7 this.timeout = config.getTimeout(); 8 } 9// 以下省略... 10}

メリットとしては、何か設定値をいっぱい渡したいときに、設定値をひとつのクラスにまとめておくことができます。

投稿2021/07/27 17:49

編集2021/07/27 18:06
kiino

総合スコア539

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

以下コードではエラーになっているのではなく、他箇所でエラーになっているかと思います。

StudentRepository studentRepository = new StudentRepositoryImpl("C:/mydata/StudentName.csv");

通常Springで@Repositoryをつけたクラスはコンポーネントになり、Springコンテナ内Beanとして管理されます。これを実現するためにSpring起動時に各種Beanの初期化が発生するのですが、この時にStudentRepositoryImplのインスタンス化が発生し、引数のStringが取得できないと判断されエラーになっているかと思います(コンストラクタインジェクションなどでググってみてください)。

また、前述のとおり、StudentRepositoryImplはBeanとして管理しているため、DIして利用すべきです。そのため「new」を使って利用してはいけません。
よって、Repositoryクラスで作ったコンストラクタで引数を渡すことはできません。また、RepositoryクラスはSingletonなので、基本以下のようにしても同じかと思います。

java

1@Repository 2public class StudentRepositoryImpl implements StudentRepository { 3 private String dataName; 4 public StudentRepositoryImpl() { 5 this.dataName = "C:/mydata/StudentName.csv"; 6 }

最後に、そもそも論ですが"C:/mydata/StudentName.csv"というファイルパスをコンストラクタ引数で渡すという設計がまちがっているかと思いますので、クラス設計から見直すことをお勧めいたします。

投稿2021/07/27 12:27

momotuwo

総合スコア155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manudon

2021/07/27 14:19

その外からオブジェクトを注入する DIのやり方を知りたいです
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問