스프링 원리

Soeng_dev·2023년 4월 21일
0

스프링 공부

목록 보기
1/2

스프링 핵심 원리 이해

  • 여러 정책(ex:할인정책)가운데 어떤걸 쓸지 확정되지 않은 경우 인터페이스를 이용해 구현

• IoC (Inversion of Control)

프로그램의 제어 흐름을 구현객체가 직접 담당하는게 아닌 외부에서 관리하는것

• IoC 컨테이너, DI 컨테이너

  • 객체 생성 및 관리 의존관계 연결해주는 역할을 해주는게 DI컨테이너( = IoC컨테이너, 어셈블러, 오브젝트 팩토리)

  • DI 컨테이너 사용시, 별도의 설정 클래스를 만들어 DIP, OCP, SRP 원칙을 지킬 수 있음
    -> 구현객체(구체클래스)의 생성/연결하는 책임을 설정클래스로 분리가능 - 일반 객체들은 자기 역할을 수행하는것만 집중 가능
    -> 인터페이스에만 의존(DIP)
    -> 설정클래스의 코드만 고치고 클라이언트 코드는 손댈게 없음(OCP)

  • 자바 스프링을 이용하면 이게 쉽게 가능

» 프레임워크, 라이브러리

라이브러리

제어의 흐름을 내가 작성한 코드가 담당한다면 라이브러리

프레임워크

내 코드를 대신 제어하고 실행한다면 프레임워크

• 클래스 다이어그램

인터페이스에 들어갈 수 있는 구체클래스들까지 표시

• 객체 다이어그램 (오브젝트 다이어그램)

실제 new를 통해 실행시 동적으로 객체들의 연관관계가 어떻게 맺어지는지 나타낸것(인스턴스간의 관계 다이어그램)

• 참고

  • 스프링에 test 패키지에 코드 작성하면 배포 시 테스트코드는 자동으로 빼고 배포

  • HashMap은 동시성 이슈있음, 실무에선 ConcurrentHashMap주로 사용

  • 테스트 코드(테스트클래스) 만들때 ctrl + shift + t

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

• 빈 조회

  • 부모타입으로 조회하면 자식타입도 함께 조회함
    -> Object타입으로 조회 시 등록된 모든 빈을 다 조회

» getBean()

  • 설정클래스인스턴스.getBean(빈이름, 타입)

  • 설정클래스인스턴스.getBean(타입)

  • 해당 빈 없으면 'NoSuchBeanDefinitionException: No bean named 'xxxxx' available' 예외 발생

  • 빈이 리턴하는 구체클래스를 타입변수로 넣어줘도 가능은함
    -> 다만 구체클래스에 의존하는게 좋은 코드는 아님

» getBeansOfType(TargetType.class)

해당 타입의 모든 빈을 조회

» getBeanDefinitionNames()

  • 설정클래스인스턴스.getBeanDefinitionNames()
  • 등록된 모든 빈의 이름을 조회

» getBeanDefinition(beanDefinitionName)

beanDefinition 정보를 받아옴

» beanDefinition.getRole()

스프링 내부에서 사용하는 빈인지 내가 등록한 빈인지 역할을 알수 있는 메서드

  • ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
  • ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

• 스프링 컨테이너 내부구조

» 클래스 다이어그램

BeanFactory(interface)

ApplicationContext(interface)

AnnotationConfigApplicationContext,
GenericXmlApplicationContext,
XxxApplicationContext

» BeanFactory

  • 스프링 빈을 관리, 조회해줌

  • getBean()제공

» ApplicationContext

  • BeanFactory뿐만 아니라 MessageSource, EnvironmentCapable, ApplicationEventPublisher, ResourceLoader등을 상속받아 어플리케이션 개발에 필요한 부가기능 제공

  • MessageSource
    -> 한국에서 들어오면 한국어, 영어권은 영어로 출력해주는 등의 기능 제공

  • EnvironmentCapable
    -> 로컬, 개발, 운영등을 구분해서 처리

  • ApplicationEventPublisher
    -> 이벤트 발행 및 구독 모델을 편리하게 지원

  • ResourceLoader
    -> 파일, 클래스패스, 외부등에서 리소스를 조회하는 기능

» 다양한 설정 형식 지원

  • 메타정보인 BeanDefinition으로 설정정보를 추상화시켜 다양한 설정형식 지원

  • 빈 하나당 하나의 BeanDefinition이 생성됨

  • 각각의 설정 형식에 대응하는 XXXDefinitionReader로 설정형식 읽어 BeanDefinition 생성

» BeanDefinition

  • 각 형식에 대응하는 BeanDefinitionReader사용
    -> AnnotationConfigApplicationContext : AnnotatedBeanDefinitionReader
    -> GenericXmlApplicationContext : XmlBeanDefinitionReader

  • 새로운 설정 형식 추가하려면 XxxBeanDefinitionReader 만들어 BeanDefinition 생성하면 됨

BeanDefinition이 갖고있는 정보

  • BeanClassName
    -> 빈의 클래스명

  • factoryBeanName
    -> 팩토리 역할의 빈 이름 (ex: appConfig)

  • factoryMethodName
    -> 빈을 생성할 팩토리 메서드 지정

  • Scope
    -> 싱글톤(기본값)

  • lazyInit
    -> 스프링컨테이너 생성시 빈을 같이 생성할지, 실제 빈 사용시 빈을 생성할지

  • InitMethodName
    -> 메서드 주입으로 주입 시, 사용할 초기화 메서드 명

  • DestroyMethodName
    -> 빈의 생명주기가 끝나 제거시 호출되는 메서드명

  • Constructor arguments, Properties
    -> 의존관계 주입시 사용되는 정보

• 참고

  • 클래스의 정적인 의존관계는 인텔리제이에서 보여주게 하는 기능이 있음

싱글톤 컨테이너

• DI컨테이너와 싱글톤 패턴

싱글톤 패턴이 아닌 DI컨테이너를 만들면, 요청때마다 객체를 새로 만들어 메모리 낭비

» 직접 구현시 문제점

  • DIP, OCP 위반 (구체클래스에 의존할 수 밖에 없게됨)
    -> 상속관계중에 getInstance 메서드 구현된 추상클래스 상속받거나 인터페이스에 getInstance 넣어서 상속받으면 해결가능하긴 할듯
  • 싱글톤 패턴 구현에 코드가 많이 들어감

  • private 생성자로 자식클래스 만들기 어려움

  • 개체 생성을 외부에서 관여하기 어려움(생성자의 패러미터 전달 등)
    -> 내부속성 변경 및 초기화 어려움
    -> 테스트 어렵고, 유연성 떨어짐

» 스프링 컨테이너

  • 스프링 컨테이너는 자동으로 객체를 싱글톤으로 생성해줌
    -> 기본등록방식은 싱글톤, 매번 새로운 객체 생성하는 기능도 제공

  • 싱글톤의 단점 해결 - DIP, OCP, 테스트 용이, private생성자 안해도됨

  • 싱글톤 객체를 생성/관리 하는 기능을 '싱글톤 레지스트리'라고 함

• 싱글톤 방식의 주의점

  • 인스턴스를 하나만 생성해 공유 -> stateless하게 설계해야 한다
    -> 참고 : stateful한 설계란? https://bit.ly/3Whtyej

  • 특정 클라이언트에 의존적, 값을 변경할 수 있는 필드 X

  • 가급적 읽기만 가능
    -> 정 필요하다면 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal등을 사용

  • 스프링 빈의 필드에 공유값 있으면 큰 장애 발생가능성

• @Configuration을 통한 싱글톤 설정

  • @Configuration 설정시 자동으로 스프링빈(@Bean)을 싱글톤으로 생성

  • AppConfig 빈의 클래스 정보를 파라미터로 넘겨 출력해보기
    ->AnnotationConfigApplicationContext에 파라미터로 넘긴 값도 자동으로 스프링 빈으로 등록됨
    ->AppConfig.getClass()를 출력시 class hello.core.AppConfig$$EnhancerBySpringCGLIB$$bd479d70와 같이 나옴

  • 실제로 빈에 등록되는건 CGLIB(바이트코드 조작 라이브러리) 사용해 AppConfig를 상속받은 클래스
    -> 이를 통해 싱글톤 생성

컴포넌트 스캔

@Bean 없이도 자동으로 스프링 빈을 등록해줌
자동으로 의존관계 주입을 위한 @Autowired 기능도 있음

• 사용법

  • @ComponentScan으로 설정 java파일을 만들면 @Component가 붙은 모든 클래스를 스프링 빈으로 등록

  • 기본이름은 첫글자만 소문자로 바꾼 클래스명

  • 빈 이름 지정하려면 @Component("name")

» 탐색위치

  • 탐색 시작위치와 그 하위패키지 모두를 탐색

  • 기본은 @ComponentScan 붙은 설정정보 클래스의 패키지가 시작위치
    (일반적으로 시작위치 지정 안하고, 그냥 프로젝트 최상단에 설정정보를 둠)

  • 아래와 같이 시작위치 설정가능
    @ComponentScan(basePackages = "hello.core")
    @ComponentScan(basePackages = {"hello.core", "hello.service"})

• @Autowired

  • 생성자, 메서드, 필드등에 @Autowired 붙이면 스프링 컨테이너가 해당 스프링빈을 자동으로 찾아서 주입

  • 기본 조회전략은 같은 타입의 빈을 주입

» 옵션 처리

  • @Autowired(required = false)
    -> 주입 대상 없으면 메서드 호출 안됨

  • org.springframework.lang.@Nullable
    -> 매개변수에 @Nullable 어노테이션 명시해 사용
    -> 주입 대상 없으면 null이 입력

  • Optional<>
    -> 주입 대상 없으면 Optional.empty가 입력
    -> 매개변수 타입을 Optional<사용할 클래스타입>으로 받아서 사용

» 조회된 빈이 여럿일 때

NoUniqueBeanDefinitionException 오류가 발생

  • 하위타입으로 지정하는것은 DIP를 위배(유연성 떨어짐)
  • 또한 구채클래스의 타입까지 완전히 같고 클래스 이름만 다른 빈이 여러개면 해결안됨

아래 방법 사용

» 필드명 매칭

@Autowired 매칭 시 같은 타입 빈이 여러개면 필드/파라미터 의 이름으로 매칭

» @Qualifier

아래와 같이 사용, 여러개의 빈 중 @Qualifier로 지정해준 이름이 일치하는 빈 주입

@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
@Qualifier("mainDiscountPolicy") DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}

애노테이션 직접 만들기

  • @Qualifier("mainDiscountPolicy")와 같이 명시하면 컴파일시 타입 체크가 안됨
  • 아래와 같이 직접 애노테이션을 만들면 타입 체크 가능
    -> @Qualifier("mainDiscountPolicy")의 자리에 @MainDiscountPolicy
package hello.core.annotataion;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}

» @Primary

@Component 지정된 클래스에 명시하면, 여러 빈이 매칭될때 우선권을 가짐
이때 @Quilifier의 우선권이 더 높음
-> 매인으로 사용하는 빈에는 @Primary를, 가끔 서브로 사용하는 빈에는 @Qualifier를 이용하면 코드 깔끔하게 유지 가능

• 스캔 기본대상

아래 어노테이션들은 컴포넌트 스캔의 기본대상
(내부적으로 @Component 어노테이션이 명시됨, java의 상속관계가 아닌 spring이 자체적으로 지원하는 기능)

useDefaultFilters 옵션을 끄면 기본 스캔대상들이 제외됨

» @Controller

스프링 MVC 컨트롤러로 인식

» @Repository

스프링 데이터 접근 계층으로 인식
데이터 계층의 예외를 스프링 예외로 변환

» @Configuration

앞서 보았듯이 스프링 설정 정보로 인식
스프링 빈이 싱글톤을 유지하도록함

» @Service

따로 기능은 없음
핵심 비즈니스 로직이 있는곳에 주로 명시함

• 필터

컴포넌트 스캔대상 설정
includeFilter, excludeFilter

» ANNOTATION 필터타입

기본값, 애노테이션을 인식

» ASSIGNABLE_TYPE 필터타입

지정한 타입과 자식 타입을 인식

» ASPECTJ 필터타입

AspectJ 패턴 사용 (자바용 aop 확장기능)

» REGEX 필터타입

정규 표현식

» CUSTOM 필터타입

TypeFilter 이라는 인터페이스를 구현해서 처리

• 빈 중복등록

» 자동 등록 vs 자동 등록

ConflictingBeanDefinitionException 예외 발생

» 수동 등록 vs 자동 등록

수동 빈 등록이 우선권을 가짐 (수동빈이 자동 빈을 오버라이딩 해버림)
-> 에러 발생 가능성 다분, 최근 스프링 부트에선 오류가 발생토록 기본값

의존관계 자동 주입

  • 주로 생성자 주입 사용
    -> 객체의 생성부터 소멸까지 데이터를 유효한 상태로 유지해야하는 객체지향의 방향성과 맞음

  • 생성자 주입시 컴파일 단계에서 데이터 누락 파악 가능
    -> 생성자 주입에선 주입 데이터가 누락되었을때 컴파일 오류 발생
    -> 생성자 주입만 멤버변수에 final키워드 사용 가능

  • 생성자에서 설정되지 않는 필드가 있으면 컴파일 시 오류로 파악가능

  • 기본적으로 생성자 주입 사용, 필수가 아닌 값들에 대해 수정자 주입을 옵션으로 부여

• 생성자 주입

  • 불변, 필수 의존관계에 사용

  • 생성자 호출 시점에 1번만 호출되는것이 보장됨

  • 스프링 빈의 경우 생성자 딱 1개만 있으면 @Autowired 생략해도 자동 주입

» 롬복, @RequiredArgsConstructor

롬복 라이브러리의 @RequiredArgsConstructor 사용하면 final붙은 필드를 모아 생성자를 자동으로 만듦

  • 사용법
    build.gradle에 라이브러리 및 환경 추가
  1. Preferences(윈도우 File Settings) plugin lombok 검색 설치 실행 (재시작)
  2. Preferences Annotation Processors 검색 Enable annotation processing 체크 (재시작)

• 수정자 주입

  • setter 통해 의존관계 주입
    -> setter 작성하고 @Autowired지정하면 자동으로 의존관계 주입

  • 선택, 변경가능성 있는 의존관계 사용

  • 객체 설계관점에서 setter 남발하면 캡슐화 의미 사라짐...

• 필드 주입

  • 변수앞에 @Autowired만 해주면 됨(생성자, 수정자 필요 X)

  • DI프레임 워크 없다면 아무것도 할 수 없으므로 왠만하면 쓰지말것
    -> 자바 코드에서 테스트할 경우가 많은데, 이때 아무것도 할 수 없게됨 (멤버변수 값 넣기 불가능)

• 일반 메서드 주입

  • 잘 사용 안함

  • 필드를 주입받을 일반 메서드(void init())를 작성해 @Autowired 지정

• 조회한 빈들 전부 필요할때 - List, Map

  • 클라이언트가 할인의 종류를 선택한다거나 할때 조회한 스프링 빈이 전부 필요

  • Map<String, DiscountPolicy> : DiscountPolicy 타입으로 조회한 모든 스프링 빈에 대하여,
    키에 스프링 빈의 이름, 그 값으로 해당 스프링 빈을 담아준다.

  • List <DiscountPolicy> : DiscountPolicy 타입으로 조회한 모든 스프링 빈을 담아준다.

  • 해당 타입의 스프링 빈 없으면 빈 컬렉션이나 Map주입

  • 스프링 이용시 전략 패턴을 간단하게 구현 가능
    -> 한 클래스에 모든 빈을 자동 주입해 담은 다음 사용

• 주입시 자동과 수동의 기준

  • 편리한 자동 기능을 기본으로 사용
    -> 자동써도 DIP. OCP 지켜짐

  • 직접 등록하는 기술 지원 객체(공통관심사를 aop로처리시)는 수동 등록
    -> 숫자가 적고, 문제 발생시 명확히 드러나지 않음

  • 다형성을 적극 활용하는 비즈니스 로직은 수동 등록을 고민
    -> 다른 사람이 짠 클래스를 List, Map으로 주입받으면 어떤빈들이 주입되고, 각 빈들의 이름은 뭔지 파악하기 힘듦 - 여러 코드를 찾아봐야됨
    -> 알아보기 쉽게 수동빈 등록, 또는 자동쓰려면 특정패키지에 같이 묶어둘것

  • 스프링/스프링 부트가 자동으로 등록하는 빈들은 예외
    -> 그냥 기본 사용법과 의도대로 잘 사용하는게 나음

빈 생명주기 콜백

  • @PostConstruct, @PreDestroy 애노테이션을 기본적으로 사용

  • 코드 수정 불가한 외부 라이브러리 사용시 @Bean의 initMethod, destroyMethod 설정정보 사용해 콜백함수 지정

• 스프링 빈의 이벤트 라이프사이클과 콜백

  1. 스프링 컨테이너 생성
  2. 스프링 빈 생성
  3. 의존관계 주입
  4. 초기화 콜백
  5. 사용
  6. 소멸전 콜백
  7. 빈 소멸
  8. 스프링 종료

» 초기화 콜백

빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출

» 소멸전 콜백

빈이 소멸되기 직전에 호출

스프링은 크게 아래 3가지 방법의 빈 생명주기 콜백 지원

• 스프링 내부 인터페이스 상속

스프링 초기에 나온 방법, 나머지 두 방법이 더 좋아서 지금은 거의 사용X

» InitializingBean

afterPropertiesSet() 오버라이딩 통해 초기화 위한 콜백 지원

» DisposableBean

destroy() 오버라이딩 통해 소멸전 콜백 지원

• 빈 설정정보 - 초기화/종료메서드 지정

  • @Bean(initMethod = "initMethodName", destroyMethod = "closeMethodName")
    으로 지정해주면 빈 초기화 시 initMethodName(), 소멸시 closeMethodName() 호출함

  • 빈 설정정보 이므로, 스프링에 의존X

  • 코드가 아닌 설정정보를 어노테이션으로 지정하므로, 코드를 고칠 수 없는 외부 라이브러리 사용시에도 초기화 및 종료메서드 적용 가능

» 종료메서드 추론

  • destroyMethod(종료메서드)는 따로 지정하지 않아도 close, shutdown 이라는 이름의 메서드가 있으면 자동으로 호출해줌 (접근제어자 설정상 접근가능할때 되는듯, 이렇게 할거면 public까먹지 말기)

  • 종료메서드 추론기능을 쓰지 않으려면 destroyMethod = ""으로 지정하면 됨

• @PostConstruct, @PreDestroy

  • JSR-250 자바표준의 어노테이션

  • 최신 스프링에서 가장 권장 방법

  • 자바 표준기술이라 스프링 아니어도 작동

  • 다만 코드수정 불가한 외부라이브러리에 적용 못함

» @PostConstruct

초기화 콜백 함수 지정

» @PreDestroy

소멸전 콜백 함수 지정

• 참고 : 객체 생성과 초기화

  • 너무 무거운 초기화 동작은 생성자에서 분리하는게 유지보수 더 용이함
    -> 단일책임원칙, 지연로딩(프록시패턴에서의 미디어 지연로딩처럼)의 이점등 때문
  • 다만, 초기화 작업이 굉장히 단순하면 생성자에서 다 하는게 나을수도
    -> ex) 내부 값만 약간 변경하는 등

빈 스코프

  • 스프링 컨테이너가 빈을 관리하는 범위를 의미

  • 기본적으로 싱글톤 스코프로 생성됨

  • 빈을 지정하는 어노테이션(@Bean, @Component)과 함께 @Scope("prototype")과 같이 입력하면 됨

• 싱글톤

스프링 컨테이너의 시작과 종료까지 유지되는 가정넓은범위의 스코프

• 프로토 타입

  • 스프링 컨테이너가 빈의 생성, 의존관계 주입까지만 관여

  • 종료 메서드(@PreDestroy등)이 자동호출되지 않음

• 웹 관련 스코프

  • 웹환경에서만 동작, 웹 라이브러리 추가후 사용
    -> build.gradle에 implementation 'org.springframework.boot:spring-boot-starter-web' 로 웹 라이브러리 추가
    -> spring-boot-starter-web라이브러리 추가시 스프링 부트는 내장 톰켓서버를 활용해 웹서버와 스프링을 함께 실행
    -> 웹 라이브러리 있으면 AnnotationConfigServletWebServerApplicationContext 기반으로 어플 구동, 없으면 AnnotationConfigApplicationContext기반

  • 기본포트인 8080을 다른곳에서 사용중이면 main/resources/application.properties에 server.port=9090입력해 포트를 9090으로 수정

» request

  • 웹 요청이 들어오고 나갈때 까지 유지되는 스코프

  • http 요청 하나당 빈 하나씩 생성됨
    -> 서비스 계층에 매 http 요청마다 따로 요청정보를 파라미터 넘길필요 없음, 스프링이 알아서 http요청별로 관련 필드(ex: logger)를 주입해줌
    -> 서비스 계층을 웹기술에서 분리시켜, 유지보수관점에서 좋음

» request 스코프에서 빈 생성과 주입타이밍 차이로 인한 오류 해결

  • request스코프에선 http요청이 들어올때 빈 생성
    -> 먼저 생성되는 다른 빈들에서 request스코프의 빈 요청시 생성전이라 찾을 수 없음

  • ObjectProvider, Scope의 프록시 설정을 통해 해결
    -> @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)를 통해 설정
    -> 적용대상이 인터페이스라면 ScopedProxyMode.INTERFACES선택
    -> ObjectProvider는 아래 내용 참고

» session

웹 세션이 생성되고 종료될때까지 유지

» application

웹 서블릿 컨텍스트와 같은 범위로 유지되는 스코프

• 스코프 프록시기능

  • 진짜 객체조회를 꼭 필요한 시점까지 지연하기위한 목적

  • 애노테이션 설정만으로 사용가능

  • 웹스코프 아니어도 사용가능

  • 꼭 필요한 곳에만 최소한으로 사용
    -> 이러한 특별한 scope는 무분별하게 남발하면 유지보수 힘들어짐

» 동작 원리

  • CGLIB 라이브러리 통해 바이트코드 조작, 원본 클래스를 상속받은 프록시 객체를 생성
    -> 클래스 이름 출력하면 ClassName$$EnhancerBySpringCGLIB 이라고 뜸

  • 스프링 컨테이너에 프록시 객체를 등록, 의존관계도 프록시 객체가 주입됨

  • 프록시 객체에는 요청이 들어오면 원본 객체의 빈을 요청하는 위임로직
    -> 다형성 통해 클라이언트는 상속받은 프록시 객체를 원본객체처럼 사용

• Dependency Lookup

  • 직접 필요한 의존관계를 찾는것
    -> 의존관계를 컨테이너에서 자동으로 주입받는것이 아님

  • 매번 새로운 빈을 주입받아 사용해야한다면 DL 사용해야함

  • 싱글톤 빈 내부에서, 어떤 기능 수행할때마다 새로운 프로토 타입 빈을 생성해 사용하려면 DL기능을 써야됨
    -> 멤버변수로 자동 주입 받으면, 싱글톤 빈의 초기화가 한번만 이뤄지므로 프로토타입빈의 자동주입도 한번만 이뤄짐
    -> 의도와 어긋날 가능성

  • 그렇다고 스프링 컨테이너를 싱글톤 빈의 멤버 변수로 사용하면 안됨
    -> 컨테이너에 종속적인 코드: 스프링이 아닌 다른컨테이너 사용시 코드 수정해야됨
    -> 단위테스트 어려워짐 : 간략히 테스트 위해 mock만들때 ApplicationContext는 많은 상위인터페이스들의 메서도들을 다 구현해야 하지만, DL클래스들은 비교적 간단히 구현 가능

» 스프링 ObjectFactory, ObjectProvider

  • 스프링이 제공하는 DL기능

  • ObjectFactory에 편의기능을 추가해 ObjectProvider가 만들어짐

  • ObjectProvider<TargetType> variableName; 으로 선언해 사용

  • 내부적으론 스프링 컨테이너를 통해 해당 빈을 찾음
    -> 하지만 기능이 단순해 mock이나 단위테스트 만들기는 훨씬 쉬움 (스프링 컨테이너를 직접사용하는 것에 비해)

  • getObject()를 통해 빈을 받음

» JSR-330 Provider

  • JSR-330 자바 표준에서 제공하는 DL : javax.inject.Provider
    -> 스프링 부트 3.0은 jakarta.inject.Provider을 사용
    -> 자바 표준이므로 스프링이 아닌 다른 컨테이너에서도 사용 가능

  • gradle에 해당 라이브러리를 추가해서 사용

  • 기능이 단순해 단위테스트, mock 코드를 만들기 쉬움

  • get()을 통해 빈을 받음

» JSR-330 Provider vs ObjectProvider

  • ObjectProvider는 DL 관련한 편의기능을 많이 제공해 편리함
    -> 기본적으로 ObjectProvider 사용

  • 스프링이 아닌 다른 컨테이너에서도 사용할수 있어야만 한다면 JSR-330 Provider 사용

  • 보통 스프링과 자바 표준이 제공하는 기능이 겹치면, 스프링 쪽이 더 편리한 기능 제공함
    -> 다른 컨테이너 쓸일 없다면, 스프링 기능 사용

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

»

profile
Software Engineer

0개의 댓글