객체의 생성부터 생명주기 관리를 프레임워크(컨테이너)가 도맡아서 한다.
= 제어권이 개발자에서 컨테이너로 넘어가게 되는 현상
스프링이 실행될 때 모든 의존성 객체를 다 만들어주고 필요한 곳에 주입시켜 준다.
객체를 직접 생성하는 것이 아니라 외부에서 생성한 후 주입시켜주는 방식
모듈 간 결합도가 낮아지고 유연성이 높아진다.
의존성을 입력 받는 setter 메서드를 만들고 이를 통해서 의존성을 주입한다.
@Component
public class SampleController {
private SampleRepository sampleRepository;
@Autowired // 있어도 되고, 없어도 됨
public void setSampleRepository(SampleRepository sampleRepository) {
this.sampleRepository = sampleRepository;
}
}
Spring Framework Reference에서 권장하는 방법
@Component
public class SampleController {
// final을 사용할 수 있다.
private final SampleRepository sampleRepository;
public SampleController(SampleRepository sampleRepository) {
this.sampleRepository = sampleRepository;
}
}
변수 선언부에 @Autowired
어노테이션을 붙인다.
@Component
public class SampleController {
@Autowired
private SampleRepository sampleRepository;
}
1. 구동 시 순환 참조 확인 가능
의존성 주입하는 시점
이 다르다.구동 시 순환 참조 확인 불가능
구동 시 순환 참조 확인 가능
순환 참조 문제
A클래스가 B클래스의 Bean을 주입받고, B클래스가 A클래스의 Bean을 주입받는 상황
2. final 키워드 사용 가능
final
을 사용 3. Lombok의 어노테이션 @RequiredArgsConstructor
을 활용하여 간단히 작성
@Component
public class Example1 {
private final Example2 example2;
public Example1(Example2 example2) {
this.example2 = example2;
}
public void playMusic() {
example2.playGame();
}
}
// Lombok 어노테이션을 통한 의존성 주입
@Component
@RequiredArgsConstructor
public class Example2 {
private final Example1 example1;
public void playGame() {
example1.playMusic();
}
}
3. 테스트 코드를 작성하기 쉽다.
@Service
public class ExampleService {
@Autowired
private ExampleRepository exampleRepository;
public void save(int seq) {
exampleRepository.save(seq);
}
}
public class ExampleTest {
@Test
public void test() {
ExampleService exampleService = new ExampleService();
exampleService.save(1);
}
}
결과
SOLID(객체 지향 설계 원칙)
의 OCP(개방-폐쇄 원칙, Open-Closed Principle)
을 위반하게 된다.
생성자 주입 방식을 이용하면 아래와 같이 작성할 수 있다.
@Service
public class ExampleService {
private final ExampleRepository exampleRepository;
public ExampleService (ExampleRepository exampleRepository) {
this.exampleRepository = exampleRepository;
}
public void save(int seq) {
exampleRepository.save(seq);
}
}
public class ExampleTest {
@Test
public void test() {
ExampleRepository exampleRepository = new ExampleRepository();
ExampleService exampleService = new ExampleService(exampleRepository);
exampleService.save(1);
}
}