@Autowired는 스프링 컨테이너(스프링에서 자바 객체들을 관리하는 공간)에서 생성된 Spring Bean을 원하는 곳에 주입해주는 어노테이션으로,

@Autowired가 무엇인지 알기 위해서는 Spring bean과 의존성 주입이란 무엇인지 알아야한다.


@SpringBean

보다 쉬운 이해를 위해 ‘A’라는 클래스는 유저를 찾는 기능(ex:findById)이 필요하며, UserRepositroy에 해당 기능이 있다고 가정해보자.

private final UserRepository userRepository = new UserRepository();

‘A’ 클래스는 UserRepositroy에 있는 기능을 사용하기 위해  new UserRepository(); 를 통해 새로운 인스턴스를 만들어야할 것이다.

이때의 문제점은 ‘B’라는 클래스에서도 UserRepository가 필요할 경우 A,B에서 각각 다른 인스턴스를 생성하게 된다는 것이다.

B에서는 B에서 생성된 UserRepostiroy를 이용할 것이고, A클래스에서는 A에서 생성된 UserRepostiroy를 이용할 것이다. A 하고 B가 각각 다른 repository를 이용하게 된다는 점에서 명확한 코드라 할 수 없으며 코드 수정에도 어려움을 겪게된다.

이를 위해 스프링에선  Spring Bean, 즉 스프링 컨테이너에서 관리되는 인스턴스가 존재한다.

Spring Bean으로 등록하기 위해선

원하는 코드 위에 @Component를 붙임으로서 해당 클래스를 스프링이 Spring Bean으로 등록하도록 만들 수 있다.

( @Controller, @Service, @Repository, @Configuration는 @Component의 상속을 받기 때문에 해당 어노테이션이 붙으면 @Component를 안해도 됨)

따라서 예제에서 UserRepository 클래스에 @Repository를 추가함으로서 Spring Bean에서 UserRepostirory을 관리할 수 있다.


의존성 주입이란?

의존성 주입은 객체가 의존하는 또 다른 객체를 외부에서 선언하고 이를 주입받아 사용하는 것을 말한다.

다시 말해 위의 예제에서 @Repository를 통해 UserRepository를  스프링 빈에서 관리하기로 했다면 이제 A,B 클래스에 같은 인스턴스를 주입해 주는 일이 필요한데, 이것을 의존성 주입이라고 한다.

이를 위해 사용하는 것이 @Autowired 어노테이션이다.

  1. @Autowired 사용 예제.

`public class A { private final MemberRepository memberRepository;

@Autowired
public A(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}`

@Autowired 사용법

@Autowired는 생성자에 주입하는 방법과, 필드에 주입하는 방법 두가지로 쓸 수 있다.

  1. 생성자 주입 방법

`public class A { private final MemberRepository memberRepository;

@Autowired
public A(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}`
  1. 필드 주입 방법

public class A { @Autowired private MemberRepository memberRepository; }


스프링에서는 생성자 주입을 권장하는데, 그 이유는?

생성자 주입과 필드 주입의 차이점은

생성자 주입의 경우 생성자 호출 시점에 Bean을 주입하며, 필드 주입은 생성자를 호출한 이후에 Bean이 주입된다는 것이다.

이로 인해 생성자 주입이 필드 주입에 비해 가지는 상대적 이점은 다음과 같다.

  1. final로 선언할 수 있다. 생성자 호출이 끝나면 final은 초기화 할 수 없음으로 필드 주입에서는 final로 선언하지 못한다.

  2. 테스트 코드를 작성할 시, mockito 없이 객체를 생성함으로서 테스트 할 수 있다.

  3. 순환 참조를 방지 할 수  있다. 필드 주입에서 순환 참조를 할 경우 서버 구동중 오류가 발생하지만 생성자 주입의 경우 서버 구동 전에 순환참조가 발생했음을 알 수 있다.