2.

【Spring】@Autowiredアノテーションとは

編集
この記事の要点
  • @AutowiredSpring が Bean を自動注入するアノテーション
  • 注入方法は フィールド・コンストラクタ・セッターの 3 種類
  • コンストラクタ注入が推奨(不変・テスト容易・循環依存検出)
  • Spring 4.3 以降はコンストラクタが 1 つなら @Autowired 省略可
  • 同型 Bean が複数あると NoUniqueBeanDefinitionException@Qualifier で名前指定

 

@Autowired とは

Spring コンテナに登録された Bean を、型を一致させて自動的に注入するアノテーションです。DI(依存性の注入)の中核機能。

3 種類の注入方法

① コンストラクタ注入(推奨)

@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired  // Spring 4.3+ なら省略可(コンストラクタが 1 つの場合)
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

// Lombok を使うとさらに簡潔
@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;  // 自動でコンストラクタ生成
}

メリット:

  • 不変 (final) フィールドにできる → スレッドセーフ
  • テスト時にモックを渡しやすい(new でインスタンス化可能)
  • 必須依存が明確
  • 循環依存を検出(起動時に BeanCurrentlyInCreationException

② フィールド注入(非推奨)

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
}

デメリット:

  • final にできない(再代入可能)
  • テスト時にリフレクションが必要(または @InjectMocks など Mockito 機能)
  • 循環依存に気づきにくい(起動するが実行時に NPE)

③ セッター注入

@Service
public class UserService {
    private UserRepository userRepository;

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

用途: 任意の依存(@Autowired(required = false))を表現したい時。

同型 Bean が複数ある場合

同じインタフェースを実装した Bean が複数登録されていると、Spring はどれを注入すべきか判断できず例外が発生:

// 複数の Bean
@Service("emailNotifier")
public class EmailNotifier implements Notifier { ... }

@Service("smsNotifier")
public class SmsNotifier implements Notifier { ... }

// 単純な @Autowired は失敗
@Service
public class OrderService {
    @Autowired
    private Notifier notifier;
    // → NoUniqueBeanDefinitionException
}

解決策 1: @Qualifier で名前指定

@Service
public class OrderService {
    private final Notifier notifier;

    public OrderService(@Qualifier("emailNotifier") Notifier notifier) {
        this.notifier = notifier;
    }
}

解決策 2: @Primary で優先 Bean を指定

@Service
@Primary
public class EmailNotifier implements Notifier { ... }
// 以後、Notifier 型の注入は EmailNotifier が選ばれる

解決策 3: 全部受け取って自分で選ぶ

@Service
public class OrderService {
    private final List notifiers;  // 全 Bean を List で受け取る

    public OrderService(List notifiers) {
        this.notifiers = notifiers;
    }
}

// または Map (key = Bean 名)
public OrderService(Map notifierMap) { ... }

@Autowired(required = false)

Bean が存在しない場合でもエラーにせず、null のままにしたい時:

@Service
public class OrderService {
    @Autowired(required = false)
    private OptionalFeature optionalFeature;  // 存在しなくても OK
}

// Spring 5+ なら Optional でも同じ効果
@Service
public class OrderService {
    private final Optional optionalFeature;
    public OrderService(Optional feature) { ... }
}

循環依存(Circular Dependency)

@Service
public class ServiceA {
    private final ServiceB b;
    public ServiceA(ServiceB b) { this.b = b; }
}

@Service
public class ServiceB {
    private final ServiceA a;
    public ServiceB(ServiceA a) { this.a = a; }
}
// → BeanCurrentlyInCreationException

対処:

  • 設計を見直す: 共通ロジックを ServiceC に切り出し
  • @Lazy で遅延注入: @Lazy private ServiceB b;
  • セッター注入に変更: 起動時には注入せず、後から設定
  • ApplicationContext から手動取得: context.getBean(ServiceB.class)(最終手段)

よくあるトラブル

Q. NoSuchBeanDefinitionException

Bean が登録されていない。原因:

  • クラスに @Component / @Service 等が付いていない
  • パッケージが @ComponentScan の範囲外
  • @Configuration@Bean の定義が漏れている
  • interface を実装した具象クラスがない

Q. private フィールドの @Autowired が null

  • new でインスタンス化している(Spring 経由でないと注入されない)
  • クラス自体が Bean として登録されていない
  • 非 Spring 管理オブジェクトから呼ばれている(リスナー・スレッド等)

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. @After
  2. @Autowired
  3. @Bean
  4. @Before
  5. @Column
  6. @Component
  7. @Configuration
  8. @Controller
  9. @Data
  10. @Entity
  11. @GeneratedValue
  12. @Id
  13. @Modifying
  14. @PathVariable
  15. @PropertySource
  16. @Repository
  17. @RequestBody
  18. @RequestMapping
  19. @ResponseBody
  20. @RestController
  21. @Service
  22. @SpringBootApplication
  23. @Table
  24. @Transactional
  25. @Value