spring framework

스프링 프레임워크 #2 - Chapter02 : 스코프

letsDoDev 2023. 9. 12. 21:07

◎ 참고 서적  |  Mastering Spring 5

 

[스프링 빈 스코프 사용자 정의]

스프링 빈은 여러 스코프로 만들 수 있으며 기본 스코프는 '싱글톤'

 

싱글톤 스코프 사용 예)

※ 싱글톤 빈의 인스턴스는 하나뿐이므로 요청(request)와 관련된 데이터를 포함할 수 없음

@Service
@Scope("singleton")
public class BusinessServiceImpl implements BusinessService

 

[빈에 사용할 수 있는 다양한 유형의 스코프]

싱글톤 대부분의 빈,  IoC 컨테이너의 인스턴스 당 하나만 사용됨
여러 참조가 조내해도 한 번만 생성됨
프로토타입 빈에 상태가 포함되어 있는 경우 사용될 스코프 타입
리퀘스트 스프링 웹 컨텍스트에서만 사용가능
요청마다 생성 처리 즉시 폐기
주로 단일 요청에 사용
세션 스프링 웹 컨텍스트에서만 사용가능
단일 사용자 고유의 데이터에 적합
애플리케이션 스프링 웹 컨텍스트에서만 사용할 수 있음

 

[기타 중요한 스프링 어노테이션]

@ScopedProxy 싱글톤-스코프 빈에 주입되는 스마트 프록시를 제공
@Component
@Service
@Repository
@Controller

@Component : 일반적인 방법
@Service: 비즈니스 서비스 레이어에서 사용됨 
@Repository: DAO 에서 사용됨
@Controller: 프레젠테이션 구성요소에 사용됨
@PostConstruce post construct 메소드 제공
@PreDirectory predestroy 메소드 제공
빈이 보유한 모든 리소스를 해제하는 데 사용되는데 리소스 누수가 방지됨

 

[★★컨텍스트 및 의존관계 주입(CDI) 어노테이션★★★]

@Inject : @Autowired와 비슷하나 필요한 속성이 없다는 차이 존재

@Named : @Component와 유사하게 명명된 구성요소 식별, @Qualifier 과 비슷한 이름으로 빈 규정 가능

@Singleton : @Scope("singleton")와 유사

@Qualifier :  스프링 어노테이션  @Qualifier 과 비슷.

사용 예)

@Named // @Repository 대신
public class DataServiceImpl implements DataService;
@Named // @Service 대신
public class BusinessServiceImpl{
	
    @Inject // @Autowired 대신
    private DataService dataService;

 

 

[스프링 컨텍스트를 사용한 JUnit 작성 + 단위테스트 방법]

- BusinessServicejavaContextTest.java

package com.mastering.spring.context;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.mastering.spring.beans.User;
import com.mastering.spring.business.BusinessService;

// 애플이케이션 컨텍스트를 시작하기 위해 러너로 사용 (= 빈 스캔 시작)
@RunWith(SpringJUnit4ClassRunner.class)
// xml 구성으로 애플리케이션 컨텍스트 시작을 위해 선언 (#1 참고, 어디서 빈 스캔 돌릴지)
@ContextConfiguration(locations = { "/BusinessApplicationContext.xml" })
public class BusinessServiceJavaContextTest {
  private static final User DUMMY_USER = new User("dummy");

 // 단위 테스트에 사용하기 위한 빈
  @Autowired
  private BusinessService service;

// 단위 테스트를 의미하는 어노테이션
  @Test
  public void testCalculateSum() {
    long sum = service.calculateSum(DUMMY_USER);
    assertEquals(30, sum);
  }

}

↑ 각 어노테이션의 역할을 파악하기 위해 "//주석 설명"을 유심히 보기로 한다.

 

 [+ @Mock 을 사용한  JUnit를 위한 단위테스트]

  : 위 JUnit 테스트와 비교해보자

package com.mastering.spring.context;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import com.mastering.spring.beans.Data;
import com.mastering.spring.beans.User;
import com.mastering.spring.business.BusinessService;
import com.mastering.spring.business.BusinessServiceImpl;
import com.mastering.spring.data.DataService;

@RunWith(MockitoJUnitRunner.class)
public class BusinessServiceMockitoTest {
  private static final User DUMMY_USER = new User("dummy");

  @Mock
  private DataService dataServiceMock;

  @InjectMocks
  private BusinessService service = new BusinessServiceImpl();

  @Test
  public void testCalculateSum() {
    BDDMockito.given(dataServiceMock.retrieveData(Matchers.any(User.class)))
    .willReturn(Arrays.asList(new Data(10), new Data(15), new Data(25)));

    long sum = service.calculateSum(DUMMY_USER);
    assertEquals(10 + 15 + 25, sum);
  }
}

 

 

:: Chapter 2  요약 :: _____

1. 의존 관계 주입과 IoC는 코드의 결합을 느슨하게 하여 테스트하기 용이하다 -> 결함 감소

2. 주요 복습 내용 - #애플리케이션 컨텍스트, #빈팩토리, #스코프