スポンサーリンク

エラー・例外

SpringBootでparameter 0 of constructor in required a bean of type that could not be found.

投稿日:

発生時のログ

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.springhack.help.controller.LoginController required a bean of type 'com.springhack.help.service.LoginService' that could not be found.


Action:

Consider defining a bean of type 'com.springhack.help.service.LoginService' in your configuration.

parameter 0 of constructor in required a bean of type that could not be found.の発生理由

@RestController
@RequestMapping("/")
public class LoginController {

    private final LoginService loginService;

    public LoginController(LoginService loginService) {
        this.loginService = loginService;
    }

    @GetMapping
    public String get() {
        String login = loginService.login("foo","bar");
        return login;
    }
}

コンストラクターでDIしたいインスタンスが、起動時に見つからない場合に発生します。

ここでは7業目でLoginServiceのインスタンスを受け取って、フィールドloginServiceにセットしようとしています。しかし、何らかの理由(後述)でLoginServiceのインスタンスが生成されなかかったため、本エラーが発生しました。

解決策 DIしたいインスタンスが生成されるようにする

人によってなぜDIしたいインスタンスが生成されなかったかは異なりますが、典型例を示します。

下記はNG例です。

@Service
public interface LoginService {
    String login(String mail, String password);
}
public class LoginServiceImpl implements LoginService {
    public String login(String mail, String password) {
        return "OK";
    }
}

上記は、サービスをインターフェースと実装クラスに分けて使用している良い例です。

しかし、@Serviceがインターフェースの方についており、実装クラスにはついていないため、bootRunした時に、LoginServiceインターフェースの実装クラスが作成されませんでした。

その結果、LoginControllerのコンストラクタでLoginServiceをDIしようとしても、インスタンス化されておらず、DI対象がないためエラーが発生します。

修正するには、下記のように実装クラスに@Serviceをつける必要があります。

public interface LoginService {
    String login(String mail, String password);
}
@Service
public class LoginServiceImpl implements LoginService {
    public String login(String mail, String password) {
        return "OK";
    }
}

Tips.1 インターフェースと実装クラスのどっちに@Serviceをつける?

 現場ではインターフェースと実装クラス、どっちに@Serviceをつけるべき?と整備されていない現場もありますが、正解は実装クラスのみつけるです。

実装クラスにもインターフェースにも両方につけても動きますが、インターフェースはあくまでインターフェースであって、インスタンス化されるべきは実装クラスの方です。

Tip2. @ComponentでもOKです

 また、サービス層ではないインテグレーション層の部品、主にAccessorを作るときにも同じことが起きますので、@Componentをつけて実装クラスがインスタンス化されるようにしてください。

Udemyのハンズオン動画講座でSpringBootのスキルを磨く!

スポンサーリンク

-エラー・例外

Copyright© 【Spring Hack】 , 2022 All Rights Reserved Powered by AFFINGER5.