teratail
質問するログイン新規登録

Q&A

2回答

7722閲覧

Springの@AutowiredでString型をDIさせる方法

yoshihiro_yy

総合スコア27

DI (Dependence Injection)

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

Java

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

Spring

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

0グッド

1クリップ

投稿2018/08/08 11:03

編集2018/08/08 11:30

0

1

SpringMVCを利用しております。

各コンポーネントの中で、xmlで定義した定数のようなものを利用したいと思い、
application-config.xmlに

xml

1<bean id="processName" class="java.lang.String"> 2 <constructor-arg value="xxxx" /> 3</bean>

このように記述しBeanを定義し、これを各コンポーネント内で

Java

1@Autowired 2private String processName;

このようにフィールドインジェクションを利用しDIをさせようとしたところ、以下エラーが発生し上手くいきませんでした。

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

DIの候補で一致する型が複数(もしくは0?)件の場合に出るエラーだったかと思いますが、他にjava.lang.String型でBean定義をしていないのです。

その後試行錯誤していたところ、

Java

1@Autowired(required=false) 2private String processName;

とすると、期待通りエラーも出ず「processName」に「xxxx」という文字列がDIされていました。
上記required=falseはAutowiredでDIさせるBeanが見つからなかった場合にエラーにしない設定だと思っていたのですが、これはどういう動きでしょうか?

上記の動作から、@Autowiredの動きですが

  1. 型から一致するBeanを探しDIさせる(required=falseが設定されていない場合ここで見つからなければ例外発生)
  2. 次に名前で一致するBeanを探しDIさせる
  3. それでも見つからない場合はnullの状態のままとする(DIさせない)

こういった動きなのでしょうか?

もしそうなのであれば、

@Qualifier("")
@Resource

でもDIさせられるかと思い

Java

1@Qualifier("processName") 2private String processName; 3 4@Resource 5private String processName; 6 7@Resource(name="processName") 8private String processName;

こう試しましたが、これらも例外が発生し上手くDIさせられませんでした。
(xmlでbeanにQualifierで命名する方法が検索したのですがよく分からず・・・)

私の希望するDIとしては、

@Autowired(required=false)

これが最善策なのでしょうか?


上記では駄目でした

質問投稿後も、まさかと思い色々試していたのですが

Java

1@Autowired(required=false) 2private String processName;

これはあくまでも型で一致するBeanを引っ張って来ているだけのようでした。
てっきり変数名と一致するIDのBeanをDIしているのかと思っていました。
なので

Java

1@Autowired(required=false) 2private String processNameaaaaa;

といったふうに変えてもDIされていて、
上記@Autowiredの記述の状態(変数名がprocessNameaaaaa)で

xml

1<bean id="processName" class="java.lang.String"> 2 <constructor-arg value="xxxx" /> 3</bean> 4<bean id="testName" class="java.lang.String"> 5 <constructor-arg value="aaaa" /> 6</bean>

と、String型のbeanを複数定義したところ

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected single matching bean but found 2: processName,testName

と例外が発生してしまいました。

そこで改めて以下のようにしたところ希望通りの動きになりました

Java

1@Autowired(required=false) 2@Qualifier("processName") 3private String processNameaaaaa;

xml

1<bean id="processName" class="java.lang.String"> 2 <constructor-arg value="xxxx" /> 3</bean> 4<bean id="testName" class="java.lang.String"> 5 <constructor-arg value="aaaa" /> 6</bean>

上記だと問題なく「processNameaaaaa」には「xxxx」がDIされていました。
そうなってくると色々と理解ができないのですが

@Autowired(required=false)

これを設定した時点で型によるDIは失敗しているのかと思えば、型によるDIをしていたようですし、
併記する形で

@Qualifier("processName")

を記述したらprocessNameというIDのbeanをDIさせていますし、意味が分かりません。。。
なぜ

@Autowired
private String processNameaaaaa;

@Qualifier("processName")
private String processNameaaaaa;

@Autowired
@Qualifier("processName")
private String processNameaaaaa;

これらではDIさせられないのでしょうか・・・

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

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

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

コメントの取得に失敗しました

回答の取得に失敗しました

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

ただいまの回答率
%

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

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

質問する

関連した質問