본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로웹 개발 › 백엔드 › Spring

[스프링] 자동으로 빈 와이어링하기(Bean Auto Wiring)

목차

[스프링] 자동으로 빈 와이어링하기(Bean Auto Wiring)

빈 와이어링 설정하는 방법은 2가지가 있다.

1. Component Scanning : Spring Application Context에서 생성되는 빈을 자동으로 설정

2. Auto Wiring : 스프링이 자동으로 빈 의존성을 충족시키는 것.

1. Component Scanning

(1) XML을 이용한 방법

(2) 클래스에서 @ComponentScan을 이용한 방법

  • <context:component-scan base-package=“패키지명”/> 을 이용하면된다.
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd

		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">

	<context:component-scan base-package="com.spring.study"/>

</beans>

(2) 클래스에서 @ComponentScan을 이용한 방법

  • @ComponentScan(basePackages=“패키지명”) 을 사용하면된다.
@Configuration

//@ComponentScan("com.spring.study")

@ComponentScan(basePackages="com.spring.study")

public class CDPlayerConfig {

}

2. Auto Wiring

@Autowired 는 생성자, 메서드, 필드에서 사용할 수 있는 annotation 이다.

Ex)

  1. 인터페이스 정의
public interface CDPlayerDisc {

	public void play();

}
public interface MediaPlayer {

	public void play();
}
  1. 구현 클래스 정의
@Component

public class SgtPlayer implements CDPlayerDisc {

	@Override

	public void play() {

		System.out.println("Play Music Start~~");

	}

}
@Component

public class CDPlayer implements MediaPlayer {

	private CDPlayerDisc disc;

	@Autowired // CDPlayerDisc 빈이 없으면 시작 단계에서 실패

	public CDPlayer(CDPlayerDisc disc) {

		this.disc = disc;

	}

	@Override

	public void play() {

		disc.play();

	}

}
  1. 결과 테스트
@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes = CDPlayerConfig.class)  //2번

//@ContextConfiguration(locations= "classpath:context.xml") //1번

public class TestPlay {

	@Autowired
	private CDPlayerDisc cdPlayerDisc;

	@Autowired
	private MediaPlayer mediaPlayer;

	@Test
	public void cdShouldNotBeNull() {
		assertNotNull(cdPlayerDisc);
	}

	@Test
	public void testMedia() {
		mediaPlayer.play();
	}
}

스캔과 주입은 서로 다른 단계

@ComponentScan은 지정한 패키지에서 빈 후보를 찾는 단계다. @Autowired나 단일 생성자의 주입은 이미 등록된 빈 중에서 필요한 타입을 고르는 단계다. CDPlayer를 만들 때 SgtPlayer가 스캔 범위 밖이라면 CDPlayer의 생성자에 아무리 @Autowired를 붙여도 구현을 찾지 못한다.

flowchart LR
  A["컴포넌트 스캔"] --> B["SgtPlayer 빈 정의"]
  A --> C["CDPlayer 빈 정의"]
  B --> D["CDPlayerDisc 후보 검색"]
  D --> E["CDPlayer 생성자 주입"]
  C --> E

원래 예제의 @Autowired(required=false)는 오해하기 쉽다. 유일한 생성자의 인수가 없다면 CDPlayer를 정상적으로 만들 수 없고, 이후 disc.play()도 불가능하다. 필수 협력자는 생성자에서 필수로 받는다. 정말 선택적이라면 Optional<CDPlayerDisc> 또는 아무 동작도 하지 않는 명시적 기본 구현처럼 없을 때의 동작을 코드로 정한다.

@Component
public class CDPlayer implements MediaPlayer {
    private final CDPlayerDisc disc;

    public CDPlayer(CDPlayerDisc disc) {
        this.disc = disc;
    }

    @Override
    public void play() {
        disc.play();
    }
}

생성자가 하나뿐이면 최신 Spring에서 @Autowired를 생략할 수 있다. XML 스캔 설정과 Java @ComponentScan을 모두 등록해도 의미가 같은 것은 아니다. 둘 중 어떤 ApplicationContext가 설정을 읽는지 확인한다. 특히 웹 애플리케이션에서 부모·자식 컨텍스트가 나뉘면 빈이 한쪽에만 있어 주입이 실패할 수 있다.

시작 시 NoSuchBeanDefinitionException이라면 검색 범위와 어노테이션을, 후보가 둘 이상이라면 타입과 한정자를, 생성 중 순환 오류라면 의존 방향을 본다. 빈이 정상 생성됐는데 play()가 호출되지 않으면 그때는 요청 경로와 호출 객체를 조사한다. “스캔 실패”와 “호출 실패”는 서로 다른 단계다.

참고: 컴포넌트 스캔, @Autowired 생성자 규칙.

같은 카테고리의 글