스프링 24

request 웹 스코프와 프록시

웹 스코프는 웹 환경에서만 동작한다 그중 request 웹 스코프에 대해 알아보자. Request 웹스코프는 HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프이며 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다. 다음 그림을 보자 클라이언트 A와B는 싱글톤인 Controller와 Service빈을 공통으로 가지고 request scope빈은 개별로 다른 인스턴스를 HTTP 요청을 할 시에 할당되어 가진다. request빈의 특징은 HTTP가 들어오고 나갈 때까지 유지되는 것이기 때문에 클라이언트 A가 Controller에서 request scope빈을 요청하고 그 후 Service에서 resquest scope빈을 요청을 또 하더라도 같은 인스턴스의 전용 request scope..

스프링 2023.07.26

프로토타입 스코프 빈과 싱글톤 빈을 함께 사용시 문제점

프로토타입 스코프 빈과 싱글톤 빈을 함께 사용하면 문제점이 발생할 수 있다. 아래 예시를 통해 알아보자. 위 그림에 프로토타입 스코프 빈은 count라는 0으로 초기화된 private 변수를 가지며 메서드 addCount()를 통해 count 값을 1 증가시킨다. 우리가 원하는 작동 방식은 클라이언트 A와 B가 각각의 프로토타입 스코프 빈을 할당받아 각각의 count값을 가지고 각자 addCount() 메서드를 통해서 1씩 증가시킨 count 1 값을 가지기를 원한다. 하지만. cilentBean은 싱글톤이고 cilentBean은 프로토타입 스코프 빈을 생성자로 의존관계를 주입받는다. 그럼 주입 시점에 스프링 컨테이너에 프로토타입 빈을 요청한다. 그럼 스프링 컨테이너는 프로토타입 빈을 생성해서 clien..

스프링 2023.07.25

프로토타입 스코프

빈 스코프란 이름 그대로 빈이 존재할 수 있는 범위를 뜻한다. 우리는 지금까지 컨테이너의 시작과 종료까지 유지되는 스코프를 가지는 싱글톤에 대해서 공부를 했다. 하지만 프로토타입이라는 스프링 컨테이너가 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 스코프를 가지는 프로토 타입 빈이라는 것도 있다. 빈 스코프는 @Scope애노테이션을 이용해서 지정할 수 있다. 기본 디폴트 값은 singleton이다. 프로토타입은 다음과 같이 지정할 수 있다. @Scope("prototype") @Bean PrototypeBean HelloBean() { return new HelloBean(); } 싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환하지만 프로토타입의 스코..

스프링 2023.07.24

빈 생명주기 콜백

데이터베이스 커넥션 풀, 네트워크 소켓처럼 애플리케이션시작 시점에 필요한 연결을 미리 해두고, 애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요하다. 스프링 빈은 객체를 생성하고 의존관계를 주입한 다음 필요한 데이터를 사용할 수 있는 준비가 된다. 그러므로 초기화 작업은 읜존관계주입이 끝난 다음에 해야 한다. 이를 위해서는 개발자는 의존관계 주입이 완료된 시점을 알아야 하는데 스프링은 의존관계 주입이 완료되거나 스프링 컨테이너가 종료되기 직전에 스프링 빈에게 콜백 메서드를 통해서 초기화 시점을 알려주는 여러 가지 기능을 제공한다. 요약하자면 스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 빈 사용 -> 소멸 전 콜백 ..

스프링 2023.07.24

동일 타입 2개 이상의 빈이 모두 필요할 때

동일 타입으로 조회한 빈이 모두 필요한 경우가 있다. 예를 들어 고객이 RateDiscountPolicy를 선택해서 할인을 받을지 FixDiscountPolicy를 선택해서 할인을 받을지 고를 수 있다고 생각해 보자. 이를 위해 같은 타입의 빈을 List나 Map으로 받아와야 한다. @Autowired public DiscountService(Map policyMap, List policies) { this.policyMap = policyMap; this.policies = policies; } 이렇게 Map과 List로 의존관계를 주입 받을 수 있다. Map에는 빈 이름이 key 인스턴스가 value로 저장된다. List에는 각 인스턴스가 저장되어 있다. 이렇게 두개의 discountPolicy를 주..

스프링 2023.07.22

조회 빈이 2개 이상일 때 주입받는 방법

@Autowired는 타입으로 조회한다 타입으로 조회하면 같은 타입의 빈이 2개 이상일 때 문제가 발생한다. 예를 들어 DiscountPolicy의 하위 타입인 FixDiscountPolicy, RateDiscountPolicy둘다 스프링 빈으로 등록시키고 @Autowired private DiscountPolicy discountPolicy 위와 같이 DiscountPolicy타입으로 의존관계를 주입하면 NoUniqueBeanDefinitionException오류가 발생한다. 해결방법으로 하위타입을 이용해서 의존관계를 주입하면 DIP를 위배하고 유연성이 떨어진다. 해결방법에는 크게 3가지가 있다. @Autowired 필드 명 매칭 @Qualifier사용 @Primary사용 @Autowired 필드 명 ..

스프링 2023.07.22

생성자 주입의 장점, 룸복사용

여러 가지 의존관계 주입방법이 있지만 생성자 주입을 사용하는 것이 권장된다. 대부분의 의존관계 주입이 일어나면 종료시점까지 의존관계를 변경할 일이 없고 대부분의 의존관계는 변하면 안 된다. 생성자 주입은 객체 생성 시 딱 1번만 호출되므로 불변하게 설계할 수 있다. 수정자 주입을 사용하면 setter 메서드를 public으로 열어 두어야 하는데 이러면 실수로 누군가 변경할 수 있다. 프레임워크 없이 순수한 자바 코드를 단위 테스트 하는 경우에 쉽게 가능하다. 필드에 final 키워드를 사용할 수 있다. 그러면 설정되지 않으면 컴파일 오류로 막아준다. 위와 같은 장점으로 생성자 주입을 선택하는 것이 좋다. 그리고 가끔 필요하면 수정자 주입을 선택하면 된다. 생성자 주입을 좀 더 편하게 이용하기 위해 롬복 ..

스프링 2023.07.21

다양한 의존관계 주입 방법

의존관계 주입에는 크게 4가지 방법이 있다. 생성자 주입 수정자 주입(setter) 필드 주입 일반 메서드 주입 생성자 주입 생성자를 통해서 의존관계를 주입하는 방법이다. 생성자 호출될 때 딱 1번만 호출된다 불변하고 필수 적인 의존관계에 사용한다. @Autowired public MemberServiceImpl(MemberRepository memberRepository) { this.memberRepository = memberRepository; } 보통 생성자 위에 @Autowired애노테이션을 붙여서 사용한다. 근데 생성자가 하나만 존재하면 @Autowired를 생략해도 자동주입이 된다. 수정자 주입 setter메서드를 통해서 의존관계를 주입하는 방법이다. 선택, 변경 가능성이 있는 의존관계에 ..

스프링 2023.07.19

스프링 빈 필터

컴포넌트 스캔에서 대상을 추가하거나 제외할 대상을 선택할 수 있다. MyIncluderComponent, MyExcluderComponent 애노테이션을 만들어 보자 Annotation을 선택해서 만들어 주면 된다. @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyIncludeComponent { } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MyExcludeComponent { } 테스트로 BeanA와 BeanB를 만들어서 위 애노테이션을 사용해 보자 @MyIncl..

스프링 2023.07.18

컴포넌트 스캔 탐색 위치

모든 클래스를 스캔하려면 시간이 오래 걸리기 때문에 스캔 시작 위치를 설정할 수 있다. @ComponentScan( basePackages = "hello.core", ) hello.core 패키지를 포함해서 하위 패키지를 모두 탐색한다. 여러개 지정도 가능하다. 만약 basePackages를 설정하지 않은 defalut값은 @ComponentScan 애노테이션이 붙은 클래스의 패키지로 설정된다. 그래서 권장하기를 따로 basePackages를 설정하지 않고 @ComponentScan 붙은 클래스를 프로젝트 최상단에 두는 것이다. 컴포넌트 스캔은 @Component뿐만 아니라 아래와 같은 애노테이션도 포함하여 스프링 빈에 등록한다 해당 클래스의 소스를 보면 @Component 애노테이션을 포함하고 있기 ..

스프링 2023.07.18