본문 바로가기
스프링

스프링 핵심원리

by moonstal 2022. 6. 1.

스프링 핵심원리

객체 지향 설계와 스프링

  • 스프링은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임 워크
  • 다형성
    • 역할과 구현 구분:공연-역할(인터페이스)-배우(바꿀 수 있음,구현객체)
    • 객체 인스턴스 실행시점 유연하게 변경
    • 클라이언트 변경 x
  • 객체 지향 설계 5가지 원칙(solid)
    • 단일 책임(srp): 하나의 책임-변경의 파급효과 적게
    • 개방-폐쇄(ocp): 확장에 열려있고 변경(클라이언트)에 닫힘(설정자 필요), 할인정책(고정, 정률)
    • 리스코프 치환(lsp): 정확성 유지 하위타입 인스턴스로 바꿀 수 있어야 함(자동차 엑셀은 앞으로)
    • 인터페이스 분리(isp): 특정 클라이언트 위한 인터페이스 여러개 > 범용
    • 의존관계 역전(dip): 추상화(인터페이스,역할) 의존o, 구체화x
  • 스프링 di(의존성 주입), di컨테이너 통해 ocp,dip 가능

스프링 핵심 원리

DIP 위반(구체화 의존), srp 위반(구현객체 생성,연결,실행),OCP 위반(클라이언트 변경)

private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
  • 관심사 분리 필요-> 기획자 AppConfig 구현 객체 생성, 생성자 통해 주입
  • ioc(제어의 역전): 구현 객체는 자신의 로직을 실행 ,프로그램에 대한 제어
    AppConfig -> 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것
  • DI(의존관계 주입): 실행 시점에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달 -> 클라이언트와 서버의 실제 의존관계가 연결 되는 것
  • DI 컨테이너(IoC 컨테이너): AppConfig 처럼 객체를 생성하고 관리하면서 의존관계를 연결해 주는 것
  • 스프링전환: AppConfig에 설정 구성(@Configuration), 스프링 컨테이너(ApplicationContext)에 스프링 빈으로 등록 (메서드에 @Bean, 메서드이름=스프링빈이름)
  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  MemberService memberService = applicationContext.getBean("memberService", MemberService.class);

스프링 컨테이너와 스프링 빈

  • 스프링 컨테이너 생성: new AnnotationConfigApplicationContext(AppConfig.class), AppConfig.class(구성정보)
  • 스프링 빈 이름: 메서드 이름, 직접 @Bean(name="memberService2"), 빈 이름은 항상 달라야 함
  • 빈 조회
    • 컨테이너에 등록된 모든 빈 조회: ac.getBeanDefinitionNames(), ac.getBean(beanDefinitionName)
    • ac.getBean(빈이름, 타입), ac.getBean(타입)
    • 같은 타입 빈 둘이상 오류발생-> 빈 이름 지정
    • 특정 타입 모두 조회 ac.getBeansOfType()
    • 부모타입 조회 시 자식도 조회
  • ApplicationContext(BeanFactory상속)
    • 국제화 기능, 환경변수, 애플리케이션 이벤트, 리소스 조회
    • 설정 형식: 자바, xml, groovy->BeanDefinition(스프링 빈 설정 메타 정보)

싱글톤 컨테이너

  • 스프링 없는 순수한 DI 컨테이너 요청할 때 마다 객체 생성 -> 객체 1개 생성 공유하는 싱글톤 패턴 적용 필요
  • 싱글톤 패턴 문제점: 구현 코드 많음, 구체 클래스 의존, 테스트 어렵, 내부속성 변경/초기화 어렵, 자식 클래스 만들기 어렵, 유연성 떨어짐 -> 싱글톤 컨테이너로 해결
  • 싱글톤 방식 주의점: 무상태로 설계해야함(지역변수, 파라미터, ThreadLocal)
  • @Configuration과 바이트코드 조작(CGLIB): 싱글톤 보장

컴포넌트 스캔

  • 컴포넌트 스캔: @ComponentScan을 설정 정보에 붙여주면 @Component 애노테이션이 붙은 클래스를 스캔해서 스프링 빈을 등록
  • 빈이름: 클래스명 맨 앞글자 소문자
  • @Autowired: 타입이 같은 빈을 찾아 의존관계 자동으로 주입
  • 컴포넌트 스캔 기본 대상
    • @Component
    • @Controlller: MVC 컨트롤러로 인식
    • @Service: 개발자들이 핵심 비즈니스 로직으로 인식
    • @Repository: 데이터 접근 계층으로 인식
    • @Configuration: 스프링 설정 정보로 인식, 싱글톤을 유지
  • 필터
    • includeFilters : 컴포넌트 스캔 대상을 추가
    • excludeFilters : 컴포넌트 스캔에서 제외
  • 중복 등록과 충돌(같은 빈 이름): 자동 빈 등록끼리 ConflictingBeanDefinitionException, 수동>자동, 스프링 부트는 오류

의존관계 자동 주입

  • 생성자 주입: 생성자 호출시점에 딱 1번 호출, 불변, 필수 의존관계
  • 수정자 주입(setter 주입): 선택, 변경 가능성이 있는 의존관계
  • 필드 주입: 외부에서 변경 불가, 테스트 하기 힘듦
    @Autowired
    private MemberRepository memberRepository;
  • 일반 메서드 주입: 한번에 여러 필드를 주입
  • 옵션 처리
    • @Autowired(required=false): 자동 주입할 대상 없으면 수정자 메서드 호출 안됨
    • org.springframework.lang.@Nullable: 자동 주입할 대상 없으면 null 입력
    • Optional<>: 자동 주입할 대상이 없으면 Optional.empty 입력
  • 생성자 주입 권장
    • 불변: 의존관계를 변경할 일이 없다. 불변해야 한다.
    • 누락: 수정자 의존관계 -> 의존관계 주입 누락 -> Null Point Exception / 생성자 주입 final 키워드 컴파일 오류로 알 수 있음
  • 롬복의 @RequiredArgsConstructor: final이 붙은 필드 생성자 만들어줌
  • 최근: 생성자 1개, @Autowired 생략, @RequiredArgsConstructor

조회 빈이 2개 이상

  • @Autowired 는 타입(Type)으로 조회->NoUniqueBeanDefinitionException
  • @Autowired 필드 명 빈이름으로(타입매칭시도 후 추가동작)
    @Autowired
    private DiscountPolicy rateDiscountPolicy
  • @Qualifier끼리 (서브 데이터베이스 커넥션 빈)
    @Qualifier("mainDiscountPolicy")
  • @Primary: 우선순위 (메인 데이터베이스의 커넥션)
  • @Qualifier > @Primary

조회한 빈이 모두 필요할 때, List, Map

 public DiscountService(Map<String, DiscountPolicy> policyMap,
List<DiscountPolicy> policies) {
  this.policyMap = policyMap;
  this.policies = policies;
 }

자동/수동 빈 등록 사용

  • 업무 로직 빈: 컨트롤러, 서비스, 리포지토리-> 자동
  • 기술 지원 빈:기술적인 문제나 공통 관심사(AOP)-> 수동

빈 생명주기 콜백

스프링 컨테이너 생성-> 스프링 빈 생성-> 의존관계 주입-> 초기화 콜백-> 사용-> 소멸전 콜백-> 스프링 종료

빈 생명주기 콜백 지원 방법

  • 인터페이스: InitializingBean의 afterPropertiesSet() 초기화 지원, DisposableBean의 destroy() 소멸 지원
    • 단점: 스프링 전용 인터페이스 의존, 초기화, 소멸메서드 이름 변경 불가, 코드를 고칠 수 없는 외부 라이브러리에 적용불가
  • 설정 정보에 초기화 메서드, 종료 메서드 지정: 메서드 이름 자유, 스프링 코드에 의존x, 설정 정보를 사용->코드를 고칠 수 없는 외부 라이브러리에도 초기화, 종료 메서드 적용 o, destroyMethod(기본값 추론)-> close , shutdown 자동 호출
@Bean(initMethod = "init", destroyMethod = "close")
  • @PostConstruct, @PreDestroy 애노테이션 지원: 가장 편리, 권장, 자바 표준, 외부 라이브러리에 적용 못함

빈 스코프

스코프: 빈이 존재할 수 있는 범위

  • 싱글톤
    • 기본 스코프,
    • 스프링 컨테이너의 시작과 종료까지,
    • 가장 넓은 범위,
    • 항상 같은 인스턴스의 스프링 빈을 반환
  • 프로토타입
    • 프로토타입 빈의 생성과 의존관계 주입, 초기화까지만 관여,
    • 항상 새로운 인스턴스를 생성,
    • 프로토타입 빈 관리 책임->프로토타입 빈 받은 클라이언트,
    • @PreDestroy호출 x
      @Scope("prototype")
    • 싱글톤 빈이 프로토타입 빈 주입 받을 경우 함께 유지됨
    • Provider로 문제 해결
    • 직접 필요한 의존관계 찾는 것 Dependency Lookup (DL)
      • ObjectFactory, ObjectProvider
        @Autowired
        private ObjectProvider<PrototypeBean> prototypeBeanProvider;
        ...
        prototypeBeanProvider.getObject();
      • JSR-330 Provider: 자바 표준
        @Autowired
        private Provider<PrototypeBean> provider;
        ...
        provider.get()
  • 웹 관련 스코프: 스코프의 종료시점까지 관리
    • request: 웹 요청이 들어오고 나갈때 까지
    • session: 웹 세션이 생성되고 종료될 때 까지
    • application: 웹의 서블릿 컨텍스트와 같은 범위
    • websocket: 웹 소켓과 동일한 생명주기
    • AnnotationConfigServletWebServerApplicationContext 기반
  • MyLogger -> @Scope(value = "request") -> @RequiredArgsConstructor 애플리케이션을 실행하는 시점에 싱글톤 빈 생성해서 주입하는데 -> request 스코프 빈 생성 안됨 -> 오류
  • 해결: 빈 생성 지연
    //Provider
    private final ObjectProvider<MyLogger> myLoggerProvider;

    //프록시(CGLIB): 요청이 오면 그때 내부에서 진짜 빈 요청
    @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)

 

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

'스프링' 카테고리의 다른 글

[스프링] 서블릿, JSP, MVC 패턴  (0) 2022.06.09
[스프링] 웹 애플리케이션 이해, 서블릿  (0) 2022.06.09
스프링 프로젝트  (0) 2022.01.07
IntelliJ 설치  (0) 2022.01.07
자바11 설치  (0) 2022.01.07