Spring

Spring - AutoWired

NellKiM 2024. 11. 27. 10:36
Spring Autowiring이란?
Spring Framework에서 **@Autowired**는 **의존성 주입(Dependency Injection)**을 자동으로 처리하는 데 사용되는 어노테이션입니다. Autowiring은 Spring이 개발자가 명시적으로 빈(Bean)을 설정하지 않아도 자동으로 컨테이너에 있는 적절한 빈을 찾아 주입하는 기능을 말합니다.

기본 개념
Spring에서는 객체 간의 의존성을 설정하기 위해 개발자가 XML, Java Config, 또는 어노테이션 기반으로 의존성 주입을 설정합니다.

Autowiring은 개발자가 빈을 명시적으로 설정하지 않아도, Spring 컨테이너가 자동으로 적절한 빈을 찾아 주입하는 방식입니다.
이를 통해 코드량을 줄이고, 의존성 설정을 간결하게 만듭니다.
Autowiring 동작 방식
@Autowired를 사용하면, Spring 컨테이너는 해당 필드, 생성자, 또는 메서드 파라미터와 일치하는 타입의 빈을 자동으로 찾아 주입합니다.

타입 매칭
Spring의 Autowiring은 기본적으로 타입(by type) 기반으로 동작합니다:

먼저 타입이 일치하는 빈을 찾습니다.
같은 타입의 빈이 여러 개 있을 경우, **빈 이름(by name)**을 기준으로 매칭합니다.
주입할 빈이 없는 경우, 예외를 던지거나 설정에 따라 주입하지 않을 수도 있습니다.

@Component
public class UserService {

    @Autowired
    private UserRepository userRepository; // 자동으로 UserRepository 빈 주입
}
//생성자 기반 주입


@Component
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
//생성자 기반 주입은 필드 기반보다 더 권장됩니다. (테스트와 불변성을 고려했을 때 더 유리)
//메서드 기반 주입

@Component
public class UserService {

    private UserRepository userRepository;

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

@Component
public class UserService {

    @Autowired
    public void processUser(UserRepository userRepository, NotificationService notificationService) {
        // 필요한 서비스 사용
    }
}
//Autowiring 옵션
//필수 여부 설정 (required)

//기본적으로 @Autowired는 주입할 빈이 없을 경우 예외를 발생시킵니다.
//이를 방지하고 싶다면, required=false로 설정하면 됩니다:

@Autowired(required = false)
private SomeOptionalService optionalService; // 빈이 없어도 예외 발생 X
//빈 이름 매칭 (@Qualifier)

//같은 타입의 빈이 여러 개 있을 경우, **@Qualifier**를 사용해 정확히 어떤 빈을 주입할지 지정할 수 있습니다:

@Component
public class UserService {

    @Autowired
    @Qualifier("specificBeanName")
    private UserRepository userRepository; // 특정 이름의 빈 주입
}
@Primary

//여러 개의 같은 타입 빈이 존재할 때, 특정 빈을 기본으로 사용하고 싶다면 @Primary 어노테이션을 빈에 추가합니다:

@Component
@Primary
public class PrimaryUserRepository implements UserRepository {
    // 기본적으로 이 빈이 주입됨
}


@Component
public class UserService {
    
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository; // 생성자 기반 주입
    }
}

Spring Autowiring의 내부 동작
Spring 컨테이너는 애플리케이션 컨텍스트(ApplicationContext)를 통해 관리되는 모든 빈의 메타데이터를 유지합니다.
@Autowired를 만나면, Spring은 해당 필드, 생성자, 또는 메서드 파라미터의 타입과 이름을 기준으로 적절한 빈을 검색합니다.
일치하는 빈을 찾으면 주입하고, 없는 경우 예외를 발생시킵니다.
장점
코드 간소화: 빈을 명시적으로 주입할 필요 없이 의존성을 자동으로 해결.
유지보수성 향상: 빈 설정이 간결해지고 가독성이 높아짐.
주의점
모호성 문제
같은 타입의 빈이 여러 개 존재하면 주입 대상이 모호해져 예외가 발생합니다. 이를 해결하려면 @Qualifier나 @Primary를 사용해야 합니다.
필드 주입은 권장되지 않음
테스트가 어려워지고 클래스가 불필요하게 Spring에 의존하게 됩니다. 대신 생성자 주입을 사용하는 것이 좋습니다.
Autowiring과 관련된 어노테이션
@Autowired: 가장 기본적인 Autowiring 어노테이션.
@Qualifier: 특정 빈을 지정하여 주입.
@Primary: 기본적으로 주입될 빈을 지정.
@Required: 특정 빈이 반드시 필요할 경우(스프링 5.1 이후 비권장).
@Inject: @Autowired와 유사하나, Java 표준 어노테이션(JSR-330).