의존성 주입(DI)

코코·2020년 8월 20일
0

Spring

목록 보기
3/15

의존성 주입의 세 가지 방식

스프링 DI에는 세 가지 방식이 있다.

  • set메서드 주입
  • 필드 주입
  • 생성자 주입

이 중에서 필드 주입이 사용하기 가장 간단하지만, 생성자 주입을 사용하라고 권장되고 있다. 참고

세 가지 모두 테스트 해 볼 것이다.

흐름

Market이라는 클래스를 만들고, 마켓에서 판매할 상품인 고기와 야채, 스낵 클래스를 주입하는 테스트를 해볼 것이다. Lombok과 spring-test 라이브러리를 이용할 것이다. 📖스프링 설정 참고

상품

마켓에서 판매할 고기와 야채를 클래스로 정의한다.

@Component
@ToString
public class Vegetable {
}

@Component
@ToString
public class Snack {
}

@Component
@ToString
public class Meat {
}

간단히 테스트만 할 것이므로 다른 코드는 작성하지 않았다.
@Component는 해당 클래스를 빈으로 등록하겠다고 명시하는 것이다.

마켓

마켓이라는 클래스를 정의하고 고기와 야채, 스낵을 멤버로 선언한다.

package com.coco.sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.Data;

@Component
@Getter
@ToString
@RequiredArgsConstructor
public class Market {
	//필드 주입
	@Autowired
	private Meat meat;
	
	//set 메서드 주입
	@Setter(onMethod_ = {@Autowired})
	private Vegetable vegetable;
	
	//생성자 주입
	private final Snack snack;
}

의존성 주입(DI) 테스트

Market클래스에서 Meat, Vegetable을 선언만 하고 초기화는 하지 않았다.
대신 각각 @Autowirted를 붙였을 뿐이다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class})
@Log4j
public class MarketTest {
	
	@Autowired
	private Market market;
	
	@Test
	public void testExist() {
		
		assertNotNull(market);
		log.info(market);
		log.info(market.getMeat());
		log.info(market.getVegetable());
		log.info(market.getSnack());

	}
}

결과는?

INFO : com.coco.sample.MarketTest - Market(meat=Meat(), vegetable=Vegetable())
INFO : com.coco.sample.MarketTest - Meat()
INFO : com.coco.sample.MarketTest - Vegetable()
INFO : com.coco.sample.MarketTest - Snack()

테스트 클래스에서도 Market클래스를 멤버로 선언만 하고, 초기화는 하지 않았다. 그럼에도 불구하고 정상적으로 객체가 생성되었고, Market클래스에 선언만 해뒀던 Meat,Vegetable,Snack 객체 모두 생성된 것을 확인할 수 있다. 이것이 의존성 주입이다.
생성자 주입을 권장하는 이유는, 객체 생성 시에 의존성 주입이 이루어지므로 좀 더 엄격하게 의존성 주입을 체크한다는 장점이 있다.
@RequireArgsContructor를 이용해서 단일 생성자의 묵시적 자동 주입 기능을 이용했다. 직접 생성자를 만들어서 @Autowired를 붙여도 상관은 없다.
@RequireArgsConstructor@NonNull 또는 final이 붙은 인스턴스들의 생성자를 만들어주는 Lombok의 어노테이션이다.

테스트 클래스의 어노테이션

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class})
@Log4j
  • @RunWith

    • 테스트 시 필요한 클래스를 지정한다.
      스프링은 SpringJUnit4ClassRunner클래스가 대상이다.
  • @ContextConfiguration

    • 실행되면, 어떤 설정 정보를 읽어들여야 하는지 명시한다.
  • @Log4j

    • Lombok을 이용해서 로그를 기록하는 Logger를 변수로 생성한다.
      Logger를 직접 생성하지 않아도 로그를 기록할 수 있다.

동작 방식

  1. 스프링 컨텍스트 생성
    프로젝트가 실행되면 가장 먼저 스프링 컨텍스트가 생성된다.

  2. 스프링 컨텍스트는 root-context.xml 또는 xml을 대체하는 설정 클래스 읽어서 자신이 스캔해야 할 패키지를 찾는다.

    ComponentScan(basePackages = {"com.coco.sample"})

    지정한 패키지의 클래스들 중에서 @Component가 붙은 클래스만 스프링의 Bean으로 등록한다.
    스프링 컨텍스트는 Bean으로 등록된 클래스들만 관리한다.

  3. 스프링 컨텍스트는 빈을 관리하면서, 필요하다는 요청(@Autowired)을 받으면 알맞은 빈을 찾아서 주입한다.

0개의 댓글