【Spring Boot】Bean が見つからないときの原因をやさしく解説

Java入門・実践
スポンサーリンク
スポンサーリンク

はじめに

Spring Boot を使っていると、
「Bean が見つかりません」
というエラーに出会うことがあります。

  • NoSuchBeanDefinitionException
  • Consider defining a bean of type ...
  • UnsatisfiedDependencyException

最初はびっくりしますが、 原因はだいたい決まっています。

この記事では、Bean が見つからないときの原因を
やさしく・実務で役立つ形 で整理していきます。

まずはよくあるエラーから見ていきましょう。

よくあるエラー

NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.service.UserService' available

このエラーは、
Spring が UserService の Bean を見つけられなかった
という意味です。

Bean が見つからない主な原因

@Component / @Service / @Repository を付け忘れている

最も多い原因です。

NG

Java
public class UserService { ... }

OK

Java
@Service
public class UserService { ... }

Spring はアノテーションが付いていないクラスを Bean として登録しません。

@Configuration / @Bean を付け忘れている

設定クラスでの登録漏れもよくあります。

NG

Java
public class AppConfig {
    public UserService userService() { ... }
}

OK

Java
@Configuration
public class AppConfig {

    @Bean
    public UserService userService() { ... }
}

パッケージ構成が原因で ComponentScan の範囲外になっている

Spring Boot は
@SpringBootApplication のあるパッケージ配下だけ
を自動スキャンします。

よくあるパターン

com.example.demo   ← Application
com.example.service ← スキャンされる
com.other.service ← スキャンされない

Application クラスより上の階層に置くとスキャンされません。

対策

  • パッケージを Application 配下に移動する
  • または @ComponentScan を追加する

インターフェースと実装の不一致

@Autowired でインターフェースを注入しているのに、
実装クラスが Bean 登録されていないパターンです。

NG

Java
@Autowired
private UserService userService; // ← インターフェース

@Service
public class UserServiceImpl2 { ... } // ← 実装名が違う

対策

  • 実装クラスに @Service を付ける
  • 名前を揃える
  • @Qualifier を使う

@Autowired の対象が複数ある

Bean が複数あると、Spring はどれを注入すべきかわからなくなります。

Java
@Service
public class AService implements UserService { ... }

@Service
public class BService implements UserService { ... }

対策

Java
@Autowired
@Qualifier("aService")
private UserService userService;

コンストラクタインジェクションの循環参照

A → B → A のように依存がループしていると Bean が作れません。

対策

  • 設計を見直す
  • 依存を片方向にする
  • Facade を作る

プロファイル(@Profile)が原因で Bean が読み込まれていない

Java
@Profile("dev")
@Service
public class DevUserService { ... }

本番環境で dev プロファイルが有効でないと Bean が登録されません。

@ConfigurationProperties のクラスに @Component を付け忘れている

NG

Java
@ConfigurationProperties(prefix = "app")
public class AppProperties { ... }

OK

Java
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties { ... }

または

Java
@EnableConfigurationProperties(AppProperties.class)

テストで @MockBean が上書きしている

テスト時に @MockBean を使うと、
本物の Bean が上書きされます。

Java
@MockBean
private UserService userService;

→ 本物の UserService が見つからないように見えることがあります。

Bean のスコープが原因

prototype スコープの Bean を注入しようとして失敗するケースもあります。

あわせて知っておきたいポイント

起動ログを見るとヒントがある

o.s.b.f.s.DefaultListableBeanFactory
のログに Bean の一覧が出ます。

Actuator で確認できる

/actuator/beans
で Bean の一覧が見られます。

Bean の仕組みを理解するとトラブルに強くなる

  • DI
  • コンポーネントスキャン
  • Bean のライフサイクル

これらがつながると理解が深まります。

使うときに気をつけたいこと

パッケージ構成を整える

Application 配下にまとめるとトラブルが減ります。

アノテーションの付け忘れに注意

@Service / @Component / @Repository は必須です。

インターフェースと実装の関係を明確に

複数実装がある場合は @Qualifier を使います。

まとめ

Bean が見つからない原因は、
「アノテーション」「パッケージ」「依存関係」
のどれかであることがほとんどです。

  • @Service / @Component の付け忘れ
  • Application 配下にない
  • 実装クラスがスキャンされていない
  • @Qualifier が必要
  • プロファイルが違う
  • 循環参照

難しく聞こえますが、
「Spring が Bean として登録できているか」
を順番に確認すれば必ず解決できます。


decopon
decopon

Bean が見つからない問題は、誰もが一度はつまずくポイントです。
原因を知っておくだけで、エラーの解決スピードが一気に上がります。
あなたの開発が、今日より少しだけ楽になりますように。

moco
moco

Bean が迷子になっちゃうこともあるんだね…ちゃんと見つけてあげたい…

コメント

タイトルとURLをコピーしました