[스프링 핵심원리 - 기본편] 섹션 7, 8, 9

‎SE-OL·2022년 7월 5일
0

7

옵션 처리

자동 주입 대상이 없으면 오류 발생,,
자동 주입 대상을 옵션으로 처리하는 방법

  • @Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨
  • org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력된다.
  • Optional<> : 자동 주입할 대상이 없으면 Optional.empty 가 입력된다.

생성자 주입

왜 생성자 주입인가 ?
=> 불변

  • 대부분의 의존관계 주입은 한번 일어나면 애플리케이션 종료시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안된다.(불변해야 한다.)
  • 수정자 주입을 사용하면, setXxx 메서드를 public으로 열어두어야 한다.
  • 누군가 실수로 변경할 수 도 있고, 변경하면 안되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다.
  • 생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일이 없다. 따라서 불변하게 설계할 수 있다.
    누락,,
    수정자 주입 등의 나머지 주입 방식은 모두 생성자 이후에 호출 되므로 final 키워드 사용 불가 -> 생성자 주입만 final 사용 가능 !!

롬복

여러가지 @Annotation을 제공하고 이를 기반으로 반복 소스코드를 컴파일 과정에서 생성해주는 방식으로 동작하는 라이브러리 -> 코드 최적화하기에 딱 !

  • 는 @RequiredArgsConstructor 기능을 사용하면 final이 붙은 필드를 모아서 생성자 자동 생성

조회 빈 2개 이상 - 문제

의존 관계 자동 주입으로 해결할 수 있음.

  • @Autowired 필드 명 매칭
  • @Qualifier @Qualifier끼리 매칭 빈 이름 매칭
  • @Primary 사용

@Autowired 필드 명 매칭

타입 매칭 시도, 빈이 여러개라면 필드 이름, 파라미터 이름으로 빈 이름 추가 매칭 (타입 매칭 우선 시도)

@Qualifier @Qualifier끼리 매칭 빈 이름 매칭

추가 구분자 붙여주는 방법 -> 빈 이름 변경 X
NoSuchBeanDefinitionException 예외 발생 가능

@Primary 사용

우선 순위 설정.

@Primary, @Qualifier 활용

스프링 빈은 @Primary 를 적용해서 조회하는 곳에서 @Qualifier 지정 없이 편리하게 조회하고, 서브 데이터베이스 커넥션 빈을 획득할 때는 @Qualifier 를 지정해서 명시적으로 획득 하는 방식

우선순위

@Qualifier가 우선순위가 더 높음(자세한게 더 우선순위 가져감)

애노테이션

애노테이션은 상속 개념 X, 애노테이션 집합 기능은 스프링이 지원하는 것 !

List, Map

로직 분석

  • DiscountService는 Map으로 모든 DiscountPolicy 를 주입받는다. 이때 fixDiscountPolicy, rateDiscountPolicy 가 주입된다.
  • discount () 메서드는 discountCode로 "fixDiscountPolicy"가 넘어오면 map에서 fixDiscountPolicy 스프링 빈을 찾아서 실행한다. 물론론 “rateDiscountPolicy”가 넘어오면 rateDiscountPolicy 스프링 빈을 찾아서 실행한다.
    주입 분석
  • Map<String, DiscountPolicy> : map의 키에 스프링 빈의 이름을 넣어주고, 그 값으로 DiscountPolicy 타입으로 조회한 모든 스프링 빈을 담아준다.
  • List : DiscountPolicy 타입으로 조회한 모든 스프링 빈을 담아준다.
  • 만약 해당하는 타입의 스프링 빈이 없으면, 빈 컬렉션이나 Map을 주입한다.

자동, 수동의 올바른 실무 운영 기준

8

빈 생명주기 콜백

빈이 사라지기 직전에 안전하게 종료할 수 있는 메소드를 호출하는 것.
스프링 빈의 이벤트 라이프사이클
스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백(빈 생성, 의존관계 주입 완료 호 호출) -> 사용 -> 소멸전 콜백( 빈 소멸 직전 호출) -> 스프링 종료

빈 생명주기 콜백 지원

  • 인터페이스
  • 설정 정보에 초기화 메서드, 종료 메서드 지정
  • @PostConstruct, @PreDestroy 애노테이션 지원

인터페이스 InitializingBean, DisposableBean

  • 초기화 메서드가 주입 완료 후에 호출
  • 컨테이너의 종료 호출 이서 소멸 메서드 호출
    단점
  • 스프링 전용 인터페이스에 의존
  • 초기화 및 소멸 메서드의 이름 변경 불가
  • 외부 라이브러리에 적용 불가

설정 정보에 초기화 메서드, 종료 메서드 지정

  • 메서드 이름 자유로움
  • 스프링 코드에 의존 X
  • 외부 라이브러리에 초기화 및 종료 메서드 적용 가능

애노테이션 @PostConstruct, @PreDestroy

  • 애노테이션 하나만 붙이면 되서 매우 간편
  • 스프링 아닌 다른 컨테이너에서도 동작
  • 컴포넌트 스캔과 조합 좋음
    But, 외부 라이브러리 적용 불가 -> Bean 사용

빈 스코프

빈 스코프?
-> 서버 미리 한개만 만들어서 쓸건지 아니면 요청마다 생성해서 쓸 것인지를 결정함.

  • 싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
  • 프로토타입: 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프
  • 웹 관련 스코프
    request: 웹 요청이 들어오고 나갈때 까지 유지되는 스코프
    session: 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프
    application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프 싱글톤 빈 요청

    싱글톤 스코프의 빈 요청 -> 스프링 빈 반환 -> 같은 요청 시 같은 객체 인스턴스의 스프링 빈 반환
    프로토타입 빈 요청

    요청 -> 프로토타입 빈 생성 및 필요한 의존관계 주입 -> 클라이언트에 반환 -> 같은 요청시 항상 new 프로토타입 빈 생성 및 반환
    • 요청 마다 새로 빈 생성
    • 컨테이너는 프로토타입 빈 생성과 주입 및 초기화만 관여
    • 종료 메서드 호출 X
    • 관리는 클라이언트가 !!
      => 싱글톤 빈과 프로토타입 스코프를 함께 사용 시 주입 받는 시점에 각각 새로운 프로토타입 빈이 생성되는 문제 발생
      이는 Provider로 해결 가능
      -> ObjectFactory, ObjectProvider, JSR-330 Provider
    • ObjectFactory: 기능이 단순, 별도의 라이브러리 필요 없음, 스프링에 의존
  • ObjectProvider: ObjectFactory 상속, 옵션, 스트림 처리등 편의 기능이 많고, 별도의 라이브러리 필요 없음, 스프링에 의존
    • JSR-330 Provider : 기능 매우 단순, 별도 라이브러리 필요, 스프링 이외의 컨테이너에서도 사용 가능

웹 스코프

웹 환경에서만 동작하는 스코프로, 스프링이 스코프 종료시점까지 관리 -> 종료 메서드 호출

  • request: HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고, 관리된다.
  • session: HTTP Session과 동일한 생명주기를 가지는 스코프
  • application: 서블릿 컨텍스트( ServletContext )와 동일한 생명주기를 가지는 스코프
  • websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프

request 스코프 예제

request scope를 사용하지 않고 파라미터로 이 모든 정보를 서비스 계층에 넘길 순 있는데,, 파라미터가 많아서 지저분함. 그리고 웹 관련 정보가 웹 노관련 서비스 계층까지 넘어가기 때문에,, request scope를 쓰는 것이 좋다. -> 고객 요청 시에만 생성 ! 깔끔 !

스코프와 Provider

  • ObjectProvider.getObject() 를 호출하는 시점까지 request scope 빈 생성 지연 가능
    • 호출 시점에 HTTP 요청 진행중이라 request scope 빈 생성 정상 처리

스코프와 프록시

proxyMode = ScopedProxyMode.TARGET_CLASS(인터페이스일때는 INTERFACES) 를 추가
동작원리

  • CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입
  • 이 가짜 프록시 객체는 실제 요청이 오면 그때 내부에서 실제 빈을 요청하는 위임 로직이 들어있다.
  • 가짜 프록시 객체는 실제 request scope와는 관계 X. 그냥 가짜이고, 내부에 단순한 위임 로직만 있고, 싱글톤처럼 동작

0개의 댓글