의존성 주입 Dependency Injection
스프링에서 제어의 역전(IoC)을 구현하기 위한 방법
Autowired
의존성 주입을 처리하기 위한 가장 중요한 어노테이션 중 하나입니다.
Spring container가 Bean을 관리해줍니다. 그러면 이 빈은 해당 빈이 필요한 다른 빈을 ‘자동으로 주입’해주는 역할을 합니다.
이를 통해 객체 간의 의존성을 명시적으로 설정하지 않고도, 필요한 의존성을 자동으로 해결할 수 있습니다.
필요한 의존 객체의 타입에 해당하는 빈을 찾아 주입, 자동으로 연결해준다
생성자, 수정자, 필드에서 자동 연결을 사용할 수 있게 됨
의존성 주입의 역할 구현
@Autowired 는 클래스 내의 필드, 생성자, 또는 메서드에 붙입니다.
public class A {
@Autowired
private B b;
}
위에서는 클래스 내의 필드에 붙인 경우입니다…
스프링 컨테이너가 관리하는 빈을 자동으로 주입하도록! 지시합니다.
저 어노테이션을 달면 자동으로 주입하게 명령 내리는 것입니다.
스프링은 이 Autowired 어노테이션이 붙은 것을 보고 적절한 빈을 찾아서 주입해줍니다.
필드 주입(Feild Injection)
필드에 직접적으로 주입해주는 방식입니다.
@Component
pulbic class MyService {
@Autowired
private MyRepository myRepository;
// myRepository가 자동으로 주입됨
@Autowired
private MyService myService;
// myService가 자동으로 주입됨
}
장점: 코드가 간결해서 직관적이고, 보기가 쉽습니다.
단점: 테스트하기 어렵고, 의존성을 명시적으로 주입하지 않아 코드의 가독성과 유지보수성이 떨어질 수도 있습니다. 그래서 권장되지 않습니다!
생성자 주입(Constructor Injection)
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy; // 의존해야할 객체
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
} // 생성자를 통해 해당 의존해야할 객체들을 주입받도록 하며 @추가
}
생성자를 통해서 의존해야할 객체들을 자동으로 주입받도록 추가
해당 객체에 대하여 생성자 메서드를 작성하는데 이에 대하여 생성자 주입을을 합니다.
장점
- 객체가 생성될 때 의존성이 모두 주입되므로 불변성을 유지할 수 있습니다.
- 필수 의존성을 명시적으로 주입하여 가독성과 테스트 용이성이 향상됩니다.
- 권장되는 방법으로 거의 이 방법만 사용하고 있다고 생각해도 됩니다.
불변성을 유지할 수 있다는 건..
예시로 작성한 위의 코드만 보아도 private final로 필드 선언한 것이 보일 것입니다!
이러면 객체가 생성된 이후 해당 필드가 변경되지 않음을 final 덕에 보장받을 수 있어 불변성이 유지가 된다는 것입니다!
의존성을 명시적으로 주입한다는 건..
객체가 생성될 때 어떤 의존성이 필요한지가 코드에서 쉽게 보입니다!
저기 코드에서도 생성자에서 바로 확인이 되잖습니까
그리고 심지어 단일 생성자에서는 Autowired를 작성하지 않아도 알아서 의존성을 주입해줍니다!
테스트 용이성이 향상된다는 것은..
단위 테스트 작성에 용이합니다. 명시적으로 주입할 수 있어서, 해당 의존성을 Mock이라는 가짜 테스트용 객체로 대체해서 쉽게 주입이 가능합니다.
@Test
public class saveSuccess() {
MyRepository mockRepository = mock(MyRepository.class);
MyService myService = new MyService(mockRepository);
}
위에처럼 생성자 주입은.. 생성자 메서드는 명시적이기 때문에 작성이 굉장히 편합니다!
메서드 주입(Method Injection)
public class FooService {
private FooFormatter fooFormatter;
@Autowired
public void setFormatter(FooFormatter fooFormatter) {
this.fooFormatter = fooFormatter;
}
}
Setter 수정자 메서드에 주입성을 주는 것으로 수정자 Setter 주입이라고도 합니다.
수정자 setter 메서드에 Autowired를 추가
의존해야하는 객체의 인스턴스와 함께 setter 메서드가 자동으로 호출됨
장점 : 의존성을 나중에 주입할 수 있고, 필요시에 메서드 내에서 추가 로직을 처리할 수 있습니다.
단점 : 나중에 추가도 가능하기도 하고 그러다보니 코드가 다소 복잡해질 수도 있으며, 필드 주입보다는 낫지만 생성자 주입자보다는 선호도가 떨어집니다.
- Q) 왜 생성자 주입만 하는 이유가 뭔가요?
- 불변성 보장(Immutability)
- 테스트 용이성 향상
- 필수 의존성이 명시적이라서 코드 가독성 편함
동작 방식
Autowired는 기본적으로 타입을 기준으로 빈을 찾습니다.
즉, 주입 대상의 타입과 일치하는 빈이 있으면 자동으로 주입하는 것입니다.
(타입에 따라 움직인다 고 생각해주세요)
'프로그래밍 > Spring Boot' 카테고리의 다른 글
[Spring] Scheduler 사용하기 (0) | 2024.10.01 |
---|---|
[스프링] 자동완성 기능 (0) | 2024.10.01 |
[스프링] H2 데이터베이스 사용하기 (0) | 2024.09.03 |
[스프링] Jsoup을 통하여 스크래핑 해보기 (0) | 2024.08.30 |
[스프링] RESTful API - 404 Not Found (0) | 2024.08.27 |