전체 글 97

의존관계 자동 주입 - 애노테이션 직접 만들기

@Qualifier("mainDiscountPolicy") 이렇게 문자를 적으면 컴파일 시 타입 체크가 안된다. 이렇게 될 경우 mainDisccountPolicy처럼 오타가 나도 해당하는 코드가 문제가 발생했는지 모르고 진행될 경우가 발생한다. 애노테이션을 직접 만들어서 변경을 해주자. 1) MainDiscountPolicy를 만들자 애노테이션은 상속이라는 개념이 없다. 이렇게 여러 애노테이션을 모아서 사용하는 기능은 스프링이 지원해 주는 것이다. package hello.core.annotation; import org.springframework.beans.factory.annotation.Qualifier; import java.lang.annotation.*; @Target({ElementTyp..

의존관계 자동 주입 - 조회 빈 이 2개 이상으로 충돌이 났을때

@Autowired는 타입(Type)으로 조회한다. 때문에 부모 클래스를 상속받은 자식 클래스라면 @Componet를 통해서 언제든지 충돌이 나는 경우가 발생한다. 아래 예를 보자. package hello.core.order; import hello.core.discount.DiscountPolicy; import hello.core.member.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor public class OrderServiceImpl implements OrderService{ private final Member..

의존관계 자동 주입 - 생성자 주입을 선택해라! & 롬복과 최신 트랜드

1) DI를 사용할 때 생성자 주입을 선택해라! 과거에는 수정자 주입과 필드 주입을 많이 사용했지만, 최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다. 그 이유는 다음과 같다. 불변 대부분의 의존관계 주입은 한번 일어나면 애플리케이션 종료 시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안 된다. 수정자 주입을 사용하면 setXxx메서드를 public으로 열어두어야 한다. 이는 누군가의 실수로 변경할 수 도 있고, 변경하면 안 되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다. 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없다. 따라서 불변하게 설계할 수 있다. 2) 롬복 사용법 개발을 해보면, ..

컴포넌트 스캔 - 컴포넌트 스캔과 의존관계 자동 주입 시작하기

지금 까지 우리는 스프링 빈을 등록할 때 @Bean이나 Xml의 Bean을 사용해서 빈을 등록했다 현재 예제는 몇개가 안되어있지만, 이렇게 등록해야 될 스프링 빈이 수십, 수백 개가 된다면 누락 문제와 더불어 너무 귀찮을 것이다. 그래서 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다. 또 의존관계 주입을 자동으로 해주는 @Autowired라는 기능도 제공한다. 1) AutoAppConfig 작성 package hello.core; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import..

싱글톤 컨테이너 - @Configuration과 싱글톤

1) AppConfig를 보자 AppConfig는 일반적으로 자바를 배운 사람이라면 객체가 계속 생성될 것으로 예상한다. 예를 들면 @Bean memberService -> new MemoryMemberRepository() 호출 @Bean orderService -> new MemoryMemberRepository() 호출 하지만 위의 예측은 다르다. 이제부터 어떻게 다른 것인지 확인해보도록 하겠다. package hello.core; import hello.core.discount.DiscountPolicy; import hello.core.discount.RateDiscountPolicy; import hello.core.member.MemberRepository; import hello.core...

싱글톤 컨테이너 - 싱글톤 방식의 주의 점

1) 싱글톤 패턴의 주의할 점 싱글톤 패턴은 객체 인스턴스를 하나만 생성해서 공유하는 방식으로 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 상태를 유지하게 설계해야 된다. 무상태(stateless)로 설계해야 된다. 스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있다!!. 2) 객체 생성 package hello.core.singleton; public class StatefulService { private int price; //상태를 유지하는 필드 public void order(String name, int price) { System.out.println("name = " + name + " price = " + price); this.price = price; ..

싱글톤 컨테이너 - 웹 애플리케이션을 싱글톤 방식으로 변경

1) AppConfig의 문제점 현재 AppConfig는 사용하고 싶을 때마다 new 생성자를 통해서 메모리를 할당받고 있다. 이렇게 될 시 웹에서 사용자들이 많아질수록 메모리 부담이 심해진다. 이를 해결하고자 Singleton 방식을 사용하려고 한다. 아래 예제를 보자. 2) SingletonService 구현 package hello.core.singleton; public class SingletonService { //1. static 영억에서 객체를 딱 1개만 생성한다. private static final SingletonService instance = new SingletonService(); //2. public으로 열어 객체인스턴스가 필요히면 이 static 메서드를 통해 조회하도록 한..

스프링 컨테이너와 스프링 빈 - 다양한 설정 형식 지원 - XML로 AppConfig 설정하기

현재는 많이 사용하지 않지만 과거에는 XML로 Config설정을 하였었다. 나도 xml 빈 설정을 하는 것을 보고 예전에 학원에서 배웠던 xml 파일이 생각났었다. Config.java에서 Config.xml로 어떻게 변경하였는지 보자. 1) appConfig.xml의 경로 2) appConfig.xml의 소스 구성 3) appConfig.xml 단위 테스트 package hello.core.xml; import hello.core.member.MemberService; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support..

스프링 컨테이너와 스프링 빈 - BeanFacotry와 ApplicationContext

1) BeanFactory 스프링 컨테이너의 최상이 인터페이스이다. 스프링 빈을 관리하고 조회하는 역할을 담당한다. getBean()을 제공한다. 지금 까지 우리가 사용했던 대부분의 기능은 BeanFacotry가 제공한다. 하지만 직접적으로 우리가 사용하지는 않는다. 우리가 사용하는 영역은 ApplicationContext 2) ApplicationContext BeanFacotry 기능을 모두 상속받아서 제공한다. 애플리케이션을 개발할 때는 빈은 관리하고 조회하는 기능은 물론이고, 수많은 부가기능이 필요하다. ApplicationContext 제공하는 부가기능 메시지 소스를 활용한 구제화 기능 -> 한국에서 들어오면 한국어로, 영어권에서 들어오면 영어로 출력 환경변수 ->로컬, 개발, 운영 등을 구분해..

스프링 빈 으로 전환하기

지금까지 순수한 자바 코드만으로 DI를 적용했으며, 스프링으로 전환을 해보자.! 1) AppConfig.java 수정 @Configuration : 스프링에게 설정 정보를 제공해 주자. @Bean : 스프링 컨테이너에 해당하는 빈을 등록해주자. package hello.core; import hello.core.discout.DiscountPolicy; import hello.core.discout.RateDiscountPolicy; import hello.core.member.MemberRepository; import hello.core.member.MemberService; import hello.core.member.MemberServiceImpl; import hello.core.member.M..