Spring @Autowired

이상민·2021년 8월 20일
0

스프링

목록 보기
4/9
post-thumbnail

애너테이션을 통한 의존관계 자동 주입
스프링에는 자동으로 의존 관계를 형성해주는 Autowire 기능이 있다

1. @Autowired

1-1. 필드에 대한 Autowire

  • 생성자를 만들지 않고 애너테이션을 통해 자동으로 필드에 의존성을 주입할 수 있다
// 생성자를 통한 의존성 주입
@Service
public class SomeService {
    private final Repository repository;
    
    public SomeService(Repository repository) {
        this.repository = repository;
    }
}


// IoC 컨테이너에 의한 자동 주입
@Service
public class SomeService {
    @Autowired
    private Repository repository;
}

1-2. setter에 대한 Autowire

  • 필드에 autowire을 하면 추가적인 로직을 수행할 수 없기 때문에 아래처럼 setter 메소드를 활요해 검증을 하는등 더 다양한 작업을 할 수 있다
@Service
public class SomeService {
    private Repository repository;
    
    @Autowired
    public void setRepositorry(Repository repository) {
        validateRepo(repository);
        this.repository = repository;
    }
}

1-3. 숨겨진 생성자에 대한 Autowire

  • 사실 생성자를 통해 의존성 주입을 받는것도 autowire 기능을 사용하는 것이다. 아래처럼 Configuration을 작성해도, 스프링은 Repository를 찾아서 SomeService Bean을 등록할때 주입한다
// AppConfiguration.java
@Configuration
@ComponentScan
public class AppConfiguration {}


// Repository.class
@Repository
public class Repository {
    ...
}


// SomeService.java
// 생성자를 통한 의존성 주입
@Service
public class SomeService {
    private final Repository repository;
    
    // @Autowired 생략. 
    public SomeService(Repository repository) {
        this.repository = repository;
    }
}
  • 4.3 이전 버전의 스프링에서는 실제로 이런 경우 생성자에도 @Autowired 애너테이션을 추가해야했다. 현재는 생략 가능하다

  • 생성자가 2개 이상인 경우에는 어떤 생성자가 자동 주입을 받는지 스프링이 알 수가 없기 때문에 애너테이션을 통해 자동 주입을 명시적으로 표시해야한다


2. 복수 후보 Bean이 존재하는 경우

생성자에 인터페이스를 주입 받도록 했는데 해당 인터페이스의 구현체가 한개 이상 존재한다면, 스프링에게 어떤 구현체를 사용할지 알려줘야한다

2-1. @Primary

  • 가장 우선시 되어야하는 컴포넌트를 지정한다
@Repository
@Primary
public class MySQLRepository implements Repository {
    ...
}

2-2. @Qualifier

  • 컴포넌트에 Qualifier를 설정하고, Bean을 사용하는 부분에서 명시해준다
// MySQLRepository.java
@Repository
@Qualifier("mysql")
public class MySQLRepository implements Repository {
    ...
}


// Service.java
// 생성자로 Autowire하는 경우 
@Service
public class Service {
    private final Repository repository;
    
    public Service(@Qualifier("mysql") Repository repository) {
        this.repository = repository;
    }
}

2-3. @Profile

  • 특정 환경에서 등록할 Bean의 관리를 Profile을 통해 쉽게 할 수 있다

  • 스프링 프레임워크의 경우 하드코딩 해주거나 외부 properties 파일에 작성할 수 있다. 스프링 부트는 컴파일시 설정해줄 수도 있다

  • 아래 예시는 prod 프로파일을 설정해 Bean등록시 Repository의 구상체로 MySqlRepository가 등록되도록 한다

// 하드코딩 시 클라이언트 코드
var applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfiguration.class);
var environment = applicationContext.getEnvironment();
environment.setActiveProfiles("prod");
applicationContext.refresh();
Repository repo = applicationContext.getBean(Repository.class);


// InMemoryRepository.java
@Repository
@Profile("dev")
public class InMemeoryRepository implements Repository {}


// MySqlRepository.java
@Repository
@Profile("prod")
public class MySqlRepository implements Repository {}
profile
편하게 읽기 좋은 단위의 포스트를 추구하는 개발자입니다

0개의 댓글