이전 블로그 👉👉
2023.01.01 - [스터디/스프링] - 스프링 공부 일지 - 객체 지향 설계와 스프링
스프링 공부 일지 - 객체 지향 설계와 스프링
빠밤!! 1월 1일이 시작되면서 지원이랑 같이 스프링 스터디를 시작한다👊👊 사용할 강의 링크 👉👉 https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8
sleecode.tistory.com
오늘은 벌써 세 번째 섹션이다!!!
객체 지향 원리를 적용해보려고 한다 😁😁
이전 기획에서 새로운 할인 정책이 추가되는 환경에 놓였다고 하자!!!
(블로그에는 적지 않았지만, 강의에서는 진도가 나갔다 ㅎㅎ,,)
그렇다면 할인 정책 구현체 하나가 더 추가되는 것인데!
기존 코드를 토대로는
클라이언트 구현체인 OrderServiceImple 코드를 불가피하게 수정해야 한다 (#°Д°)
public class OrderServiceImpl implements OrderService{
...
// new FixDiscountPolicy(); 에서 변경
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
...
}
그렇다면 객체 지향 설계 원칙의 DIP와 OCP를 위반하게 된다..
사실 우리는 클라이언트 구현체가 할인 정책 인터페이스만 의존한다고 생각했지만
구현체에도 의존하는 형태였던 것이다!!
원래 계획대로 인터페이스에만 의존하도록 하려면 어떻게 해야 할까?
👉👉 누군가 클라이언트 구현체에 할인정책 구현 객체를 대신 생성하고 주입해줘야 한다!
AppConfig라는 설정 클래스를 만들어서
앞서 말한 구현 객체를 대신 생성하고 주입해자!!
그러기 위해선 먼저 해야 할 것이 있다
클라이언트에서 객체를 직접 생성하지 말고!
변수만 선언하고 생성자의 파라미터를 통해 객체를 사용하는 것이다!!
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
그리고 AppConfig에서 클라이언트 객체를 생성할 때,
해당 인터페이스 객체를 생성해서 넣어주는 것이다!
이것이 바로 생성자를 통한 의존 관계 주입이라고 한다!!!
public class AppConfig {
/** 생성자 주입 */
public MemberService memberService(){
return new MemberServiceImpl(new MemoryMemberRepository());
}
...
}
이런 식으로 코드를 수정해 주면
DIO, OCP를 지킬 수 있게 된다!!
위의 AppCofig와 같이 프로그램의 제어 흐름을 가져간다는 것을
외부에서 프로그램의 제어 흐름을 관리한다는 뜻에서
제어의 역전 IoC(Inversiont of Control)이라고 한다
그리고 이걸 해주는 것을 IoC 컨테이너 또는 DI 컨테이너라고 한다
(객체들을 조합해 준다는 의미에서 어셈블러, 오브젝트 팩토리라고도 불림)
의존 관계 주입(DI) 에는 2가지가 있다
- 정적인 클래스 의존 관계
- 동적인 객체(인스턴스) 의존 관계
정적인 클래스 의존 관계는
그냥 클래스 다이어그램을 생각하면 된다!!
어떤 인터페이스가 의존 관계이고 구현체는 뭐가 있는지 와 같은 것들이다
하지만, 여기서 이야기하려는 DI는 주로 동적인 객체 의존 관계를 의미한다
클래스 다이어그램만으로는 실제로 어떤 구현체의 객체가 주입될지 모른다
실제 런타임이 되어서야 어떤 객체가 들어가는지 확인할 수 있기 때문에 동적이다.
그렇다면 순수한 자바 코드에서 스프링을 사용해 보자!!!
AppConfig 클래스 위에 @Configuration 어노테이션을 붙이고
각 메서드에 @Bean 어노테이션을 붙이면 된다
아주 간단쓰 \( ̄︶ ̄*\))
@Configuration
public class AppConfig {
/** 생성자 주입 -> 스프링 */
@Bean
public MemberService memberService(){
return new MemberServiceImpl(memberRepsitory());
}
...
}
이렇게 하면 @Bean 이 붙은 메서드들은 스프링 컨테이너에서 스프링 빈으로 등록된다
@Configuration은 해당 클래스를 스프링 컨테이너에서 설정 정보로 사용한다
이걸 통해 싱글톤을 유지하게 해 주는데 이건 다른 글에서 설명하겠다!!!
암튼 그래서
AppCofig를 호출해서 사용했던 memberService() 대신
/** 스프링 컨테이너 사용 */
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
이렇게 해주면 간단하게 사용가능하다!!
실행을 해보면 다음과 같이 로그가 뜬다!
자세히 보면 앞서 등록된 빈들은
스프링 컨테이너에서 실행을 위해 필요한 것들을 빈으로 등록해 둔 것이고
그 밑부터는 우리가 @Bean을 붙여놓은 메서드 이름들이 반환된다!!
이걸 통해 우리는 스프링 빈의 이름이 메서드의 이름이 된다는 것도 확인할 수 있었다!!
오늘은 좀 많은 내용을 다룬 것 같다!
고냥 오늘따라 글을 많이 쓴 걸지도 ㅎㅅㅎ,,
입문용 강의에서 들었던 내용들이
차근차근 퍼즐처럼 맞아떨어지기 시작한다
조금 기분이 좋다 😁😁😁😁
암튼 오늘도
그럼 안녕!!!!!!!!!!!!!!!!!!!!!🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌
'스터디 > 스프링' 카테고리의 다른 글
스프링 공부 일지 - 기본 키 매핑 (0) | 2023.02.23 |
---|---|
스프링 공부 일지 - JPA 시작 (0) | 2023.02.16 |
스프링 공부 일지 - 도중에 만난 Enum (0) | 2023.01.04 |
스프링 공부 일지 - 객체 지향 설계와 스프링 (0) | 2023.01.01 |
스프링 공부 일지 - AOP? (0) | 2022.11.03 |