【Spring Boot】@Autowired の仕組みをやさしく解説

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

はじめに

Spring Boot を使っていると、
@Autowired をほぼ必ず目にします。

「どうやって依存が注入されているの?」
「なぜ new しなくても使えるの?」
「Bean が見つからないときはどうなるの?」

こういった疑問は、
DI(依存性注入)を理解するうえでとても大切です。

この記事では、@Autowired の仕組みを
やさしく・実務で役立つ形 で整理していきます。

まずは基本のコードから見ていきましょう。

まずはコードを確認

Java
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User find(Long id) {
        return userRepository.findById(id).orElseThrow();
    }
}

このように、
new していないのに userRepository が使える
というのが @Autowired の魔法です。

@Autowired の仕組みを一言でいうと…

「Spring が IoC コンテナから Bean を探して、自動で注入してくれる仕組み」

です。

  • 自分で new しない
  • Spring が管理している Bean を使う
  • 型に合うものを自動で見つけてくれる

これが DI(依存性注入)の基本です。

仕組みをもう少し深く理解する

Spring が Bean を作る

まず、@Component / @Service / @Repository / @Configuration などが付いたクラスは Spring の IoC コンテナに登録されます。

@Autowired を見つける

Spring は起動時にクラスをスキャンし、
@Autowired が付いているフィールド・コンストラクタ・メソッドを探します。

型に合う Bean を探す

@Autowired の型(UserRepository)に一致する Bean を IoC コンテナから探します。

見つかった Bean を注入する

一致する Bean が 1 つなら、そのまま注入されます。

@Autowired の注入方法(3 種類)

フィールドインジェクション

Java
@Autowired
private UserRepository userRepository;

最も簡単ですが、テストしにくいため実務ではあまり推奨されません。

セッターインジェクション

Java
private UserRepository userRepository;

@Autowired
public void setUserRepository(UserRepository userRepository) {
    this.userRepository = userRepository;
}

柔軟ですが、必須依存には向きません。

コンストラクタインジェクション(推奨)

Java
@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

Spring Boot では
コンストラクタが 1 つなら @Autowired を省略できます。

実務ではこれが最も推奨されます。

@Autowired がうまく動かないときの原因

Bean が登録されていない

@Service / @Component の付け忘れ。

パッケージが ComponentScan の範囲外

Application クラスより上の階層に置いてしまうパターン。

実装クラスが複数ある

Java
@Service
class AService implements UserService {}

@Service
class BService implements UserService {}

→ どちらを注入すべきかわからない。

対策

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

循環参照

A → B → A のように依存がループしていると注入できません。

@Autowired と @Qualifier の関係

@Autowired は「型」で探す

Java
@Autowired
private UserService userService;

@Qualifier は「名前」で指定する

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

Bean が複数あるときに使います。

@Autowired と @Primary の関係

デフォルトの Bean を指定したいとき

Java
@Primary
@Service
public class DefaultUserService implements UserService { ... }

複数実装があっても、@Primary が優先されます。

@Autowired と @Lazy の関係

遅延ロードしたいとき

Java
@Autowired
@Lazy
private HeavyService heavyService;

起動時ではなく、初めて使うタイミングで生成されます。

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

@Autowired はコンストラクタが 1 つなら省略できる

Spring Boot の便利機能です。

Lombok の @RequiredArgsConstructor と相性抜群

Java
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;
}

@Autowired は「依存を外から渡す」ための仕組み

new しないことでテストしやすくなります。

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

フィールドインジェクションは避ける

テストしにくく、循環参照にも気づきにくいです。

コンストラクタインジェクションを基本にする

最も安全で、Spring 公式も推奨しています。

Bean が複数あるときは @Qualifier / @Primary

曖昧な状態を避けるとトラブルが減ります。

まとめ

@Autowired は、
「Spring が IoC コンテナから Bean を探して注入する仕組み」
です。

  • Bean は @Component / @Service などで登録
  • @Autowired は型で Bean を探す
  • コンストラクタインジェクションが推奨
  • 複数 Bean があるときは @Qualifier / @Primary
  • パッケージ構成やアノテーションの付け忘れに注意

難しく聞こえますが、
「Spring が new の代わりに依存を渡してくれる」
と理解できれば十分です。


decopon
decopon

@Autowired の仕組みを理解すると、
DI の世界が一気にクリアになります。
Bean のつながりが見えるようになると、
Spring のコードがぐっと読みやすくなります。
あなたの開発が、今日より少しだけ楽になりますように。

moco
moco

new しなくても仲間が来てくれるなんて…Spring さん、やさしいね。

コメント

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