애너테이션을 통한 의존관계 자동 주입
스프링에는 자동으로 의존 관계를 형성해주는 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;
}
@Service
public class SomeService {
private Repository repository;
@Autowired
public void setRepositorry(Repository repository) {
validateRepo(repository);
this.repository = repository;
}
}
// 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개 이상인 경우에는 어떤 생성자가 자동 주입을 받는지 스프링이 알 수가 없기 때문에 애너테이션을 통해 자동 주입을 명시적으로 표시해야한다
생성자에 인터페이스를 주입 받도록 했는데 해당 인터페이스의 구현체가 한개 이상 존재한다면, 스프링에게 어떤 구현체를 사용할지 알려줘야한다
@Repository
@Primary
public class MySQLRepository implements Repository {
...
}
// 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;
}
}
특정 환경에서 등록할 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 {}