빙응의 공부 블로그
[Spring]스프링 핵심 원리 - 의존 관계 주입2 본문
📝롬복과 최신 트랜드
막상 개발을 해보면, 대부분이 다 불변이고, 그래서 다음과 같이 필드에 final 키워드를 사용한다.
그런데 생성자도 만들고, 주입받는 값을 대입하는 코드도 만들어야 한다.
스프링은 Lombok을 이용하여 간결하게 코딩이 가능하다.
생성자 자동 생성
기본코드
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
롬복 사용 코드
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
@RequiredArgsConstructor 를 이용하면 생성자를 자동 생성해준다.
getter, setter 자동생성
@Data
public class HelloLombok {
private String name;
private int age;
}
- @Data : 자동으로 getter, setter을 만들어준다.
- @getter
- @setter
- @toString
📝조회 빈이 2개 이상인 문제
@Autowired는 타입으로 조회하기 때문에 ac.getBean(DiscountPolicy.class)와 유사하다!
@Component
public class FixDiscountPolicy implements DiscountPolicy {}
@Component
public class RateDiscountPolicy implements DiscountPolicy {}
만약 이 상태에서 의존관계 자동 주입을 실행하면
NoUniqueBeanDefinitionException 오류가 발생한다.
문제 해결법
- 하위 타입을 지정 -> DIP 위반으로 유연성이 떨어진다.
- @Autowired 필드 명 매칭
- @Quilifier
- @Primary
@Autowired 필드 명 매칭
@Autowired는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 추가 매칭한다.
@Autowired
private DiscountPolicy discountPolicy
@Autowired
private DiscountPolicy rateDiscountPolicy
아래 코드로 바꾸면 문제가 사라진다.
@Qualifier 사용
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
@Qualifier("mainDiscountPolicy") DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy")
DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
@Qualifier으로 이름을 지정해 줄 수 있다.
@Primary 사용
@Primary는 우선순위를 정하는 방법이다.
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}
@Component
public class FixDiscountPolicy implements DiscountPolicy {}
정리
- @Autowired 매칭 정리
- 타입 매칭으로 매칭 결과가 2개 이상일 때 필드 명, 파라미터 명으로 빈 이름 매칭한다.
- @Qualifier 사용
- @Qualifier끼리 매칭
- 빈 이름으로 매칭한다.
- 없을 시 NoSuchBeanDefinitionException 예외 발생
- @Primary 사용
- 우선순위를 이용한 매칭
뭘 사용해야하는가?
- @Primary의 경우
- 주로 기본적으로 사용할 빈을 선택할 때 유리
- @Qualifier보다 코드가 간결하다.
- 여러 후보 중 한가지만 항상 선택되므로 유연성이 떨어짐
- @Qualifier의 경우
- 특정 상황에서 특정 빈을 사용하는 유연성이 좋음
- 여러 빈 중 명시적으로 사용 가능하다.
- 코드가 복잡해 질 수 있다. 반드시 명시적으로 사용
📝자동과 수동의 올바른 실무 운영 기준
편리한 자동 기능을 기본으로 사용하자
- 스프링이 나오고 시간이 갈 수록 점점 자동을 선호하는 추세이다. 스프링은 다양한 계층에 맞추어 일반적인 애플리케이션 로직을 자동으로 스캔할 수 있도록 지원한다.
- 설정 정보를 기반으로 애플리케이션을 구성하는 부분과 실제 동작하는 부분을 명확하게 나누는 것이 이상적이지만, 개발자 입장에서 스프링 빈을 하나 등록할 때 @Component 만 넣어주면 끝나는 일을 일일이 AppConfig 처럼 만드는 것은 번거롭다
- 그리고 결정적으로 자동 빈 등록을 사용해도 OCP, DIP를 지킬 수 있다.
로직에 따른 사용
- 업무 로직 빈 : 자동을 사용하는 것이 좋다.
- 웹을 지원하는 컨트롤러
- 핵심 비즈니스 로직이 있는 서비스
- 데이터 계층의 로직을 처리하는 리포지토리
- 기술 지원 빈 : 수동으로 사용하는 것이 좋다.
- 기술적인 문제나 공통 관심사(AOP) 처리
- 데이터 베이스 연결이나, 공통 로그 처리 등 업무 지원에 필요한 하부 기술이나 공통 기술
- 업무 로직은 숫자가 매우 많고, 한번 개발해야 하면 컨트롤러, 서비스, 리포지토리 처럼 어느정도 유사한 패턴이기 때문에 자동 기능을 적극적으로 사용하는 것이 좋다.
- 기술 로직은 업무 로직과 비교하여 수가 매우 적고, 보통 애플리케이션 전반에 걸쳐서 광범위한 영향을 미치기 때문에 가급적으로 수동을 사용하는 것이 좋다.
비즈니스 로직 중에서 다형성을 적극 활용할 대
특정 패키지를 같이 묶어두는게 좋다.
@Configuration
public class DiscountPolicyConfig {
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy fixDiscountPolicy() {
return new FixDiscountPolicy();
}
}
설정 정보만 보고 이해가 바로 되지 않는가? 이처럼 특별한 빈들은 따로 모아서 유지하자.
'Spring > 인프런_개념' 카테고리의 다른 글
[Spring]스프링 핵심 원리 - 빈 스코프 (0) | 2023.12.29 |
---|---|
[Spring]스프링 핵심 원리 - 빈 생명주기 콜백 (0) | 2023.12.29 |
[Spring]스프링 핵심 원리 - 의존 관계 주입 (0) | 2023.12.28 |
[Spring]스프링 핵심 원리 - 컴포넌트 (0) | 2023.12.27 |
[Spring]스프링 핵심 원리 - 싱글톤 컨테이너 (1) | 2023.12.26 |