初歩的な内容になりますが、Spring Bootを使って開発していると「No qualifying bean of type・・・・」ってエラーを見かけることがあります。だいたいログの内容はこんな感じです。
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.domain.repository.CustomerRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
インスタンスが見つからないよーってことはわかりますが、一応公式を確認して訳してみました
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/NoSuchBeanDefinitionException.html
※Spring4系です、多分他のVerでも同じ感じだと思います。
「BeanFactory(というSpringのDIコンテナとして中心的な役割を果たすクラス)が、定義が見つからないインスタンスの要求を受けた時にこの例外が投げられる。
これは、インスタンス定義が見つからない、インスタンスがユニーク(一意)ではない、関連するインスタンス定義がないまま手動でシングルトンインスタンスが生成された、ということを指している。」
!!??だそうです。
以下に原因と対応をメモしておきます。
原因1:アノテーションが付与されていない
初歩的なミスですが、対象クラスをコンテナ管理対象にするためのアノテーションの付け忘れです。
以下のアノテーション等があります。
・@Component
・@Controller
・@Service
・@Repository (ただし、SpringのCrudRepositoryを継承している場合はなくても大丈夫)
なので、各クラスを確認してアノテーションを付与しているか確認しましょう。
原因2:パッケージ構成がおかしい
Spring Bootでは、@SpringBootApplicationアノテーションもしくは@ComponentScanアノテーションが付いたクラスのパッケージを起点に、配下のパッケージを再帰的にスキャンして、その中から原因1で述べたアノテーションが付与されたクラスをコンテナ管理対象とします。
以下のようなイメージです。
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ ├─example ←起点となるパッケージ
│ │ │ │ │ App.java ←@SpringBootApplicationが付与されているクラス
│ │ │ │ │
│ │ │ │ ├─controller
│ │ │ │ │ └─api
│ │ │ │ │ RestCustomerResource.java ←@Controllerが付与されているクラス、コンテナ管理対象となる
│ │ │ │ │
│ │ │ │ └─domain
│ │ │ │ ├─model
│ │ │ │ │ CustomerModel.java ←アノテーションなし、コンテナ管理対象外となる
│ │ │ │ │
│ │ │ │ ├─repository
│ │ │ │ │ CustomerRepository.java ←@Repositoryが付与されているクラス、コンテナ管理対象となる
│ │ │ │ │
│ │ │ │ └─service
│ │ │ │ CustomerService.java ←@Serviceが付与されているクラス、コンテナ管理対象となる
│ │ │ │
│ │ │ └─service
│ │ │ HogeService.java ←@Serviceが付与されているクラス、だがコンテナ管理対象外となる
com.service.HogeServiceは、@Serviceアノテーションが付いていますが、起点となる「com.example」配下ではないためコンテナ管理対象外となります。
このクラスを「com.example」配下のクラスで@AutowiredをつけてDIしようとすると「No qualifying bean of type・・」エラーが発生します。
なので、パッケージ設計をしっかりやっておかしなことにならないようにしましょう。
原因3:APT等のジェネレータで自動生成されたクラスにアノテーションが付与されていない
結構ハマりがちなのがこれです。
実は自分も、Spring Boot + Doma2で2WaySQLを使うまで、でSpring Boot起動時に「No qualifying bean of type・・・・」が出ていました。
例えば、DomaではDAOの実装クラスは自動生成してコンテナ管理対象とするのですが、その時に何の設定も入れないと「No qualifying bean of type・・」エラーが発生します(自動生成されたクラスにアノテーションがないため)。
そんな時のために、Domaでは@AnnotateWithアノテーションというのが用意されていて、自動生成されたクラスにアノテーションをつけることが可能です。なのでこれを利用することで解決することが出来ました(自分の場合はdoma-spring-boot-starterのConfigAutowireableを利用しました)。
http://doma.seasar.org/apidocs/org/seasar/doma/AnnotateWith.html
http://doma.readthedocs.org/ja/stable/config/#id22
なので、独自ジェネレーター等を利用してクラスを自動生成しているプロジェクトなんかは、そのあたりの仕組みをどうやるかの検討が必要になるかと思います。
その他の原因:・・・
その他としては、今後Springを利用しながら発生ベースで書き足したいと思います。