본문 바로가기
Java/Spring

[Spring] Bean 설정, 컴포넌트 스캔(Component Scan)

by WaterPunch 2021. 6. 1.

1. Bean 설정 방법

방법 설명
XML 기반 설정 방식 XML 파일을 사용하는 방법
<bean> 요소의 class 속성에 FQCN(Fully-Qualified Class Name)을 기술하면 빈이 정의됨
<bean id="" class="">으로 bean 생성
<constructor-arg> 또는 <property> 요소를 사용해 의존성주입(DI)
Annotation 기반 설정 방식 @Component 계열 Annotation이 명시된 클래스를 탐색(Component Scan)해서 IoC Container에 Bean을 자동으로 등록하는 방법
Java 기반 설정 방식 @Configuration을 Java Class에 명시하여 설정하고 @Bean을 사용해 bean을 정의하는 방법

(XML + Annotation 방식 또는 Java class + Annotation 방식 의 조합으로 주로 설정한다)

 

1-1  Java 기반 Bean 설정 방법

 - Java 기반 설정 방식에서는 자바코드로 Bean을 설정 - 이때 사용되는 Java class 를 Java Configuration이라고 함

@Configuration  // (1)
public class SpringConfig {

	@Bean   // (2) 
    public MemberService memberService(){
    	return new MemberServiceImpl();	// (3)
    }
    //<Bean id=memberService>으로 빈이 등록이 되었다
    //이렇게 Bean을 config.class에 등록을 해주고
    //해당 빈의 클래스에 가서 @Component("bean 이름") 을 해주면 bean이 연결이 된다
}
// 클래스 명 위에 @Component를 붙여준다
// @Componenet("bean 이름") 과 같이 빈 이름(id)를 지정할 수 있다
// 이는 xml 방식의 <Bean id="bean 이름" class="파일위치">와 동일한 표현이다

@Component("memberService")  
public class MemberServiceImpl implements MemberService{

}
AnnotationConfigApplicationContext context
	= new AnnotationConfigApplicationContext(SpringConfig.class);
    
MemberService memberService = context.getBean(MemeberService.class);

① 클래스에 @Configuration 을 붙여 설정 클래스를 선언

     - @Configuration 은 1개 이상 Bean을 등록하고 있음을 명시하는 어노테이션

② 메서드에 @Bean 을 붙여 빈을 정의

     - 메서드명이 Bean의 이름이 되고 그 Bean의 인스턴스가 반환값이 됨

   - 개발자가 직접 제어가 불가능한 외부 라이브러리 또는 설정을 위한 클래스를 Bean으로 등록할 때

     @Bean 어노테이션을 활용한다

③ 다른 컴포넌트를 참조해야 할 떄는 해당 컴포넌트의 메서드를 호출

     - 메서드에 매개변수를 추가하는 방법으로 다른 컴포넌트의 의존성을 주입 할 수 있음

        (인수로 전달될 인스턴스에 대한 Bean은 별도로 정의 되어 있어야 한다)

     - DI가 프로그램적인 방법으로 처리됨

 

@Bean 어노테이션의 경우 주로 아래와 같은 상황에서 주로 사용

   1. 개발자가 직접 제어가 불가능한 라이브러리를 사용할 때

   2. 초기에 설정을 하기 위해 활용할 때

 

@Configuration 없이 @Bean 만 사용해도 스프링 빈으로 등록이 된다

대신 메서드 호출을 통해 객체를 생성할 때 싱글톤을 보장하지 못한다

그렇기 때문에 Spring 설정 정보를 위해서는 반드시 @Configuration 을 사용해주어야 한다

 

빈의 설정을 담당하는 @Configuration 어노테이션도 내부적으로 @Component를 가지고 있어

@Configuration 이 붙은 클래스도 Spring 의 빈으로 등록이 된다

 

1-2  XML 기반 Bean 설정 방법

- XML 기반 설정 방식은 XML 파일을 이용해 Bean을 설정

 

   1-2-1 생성자(constructor) 기반 의존성 주입 방식

<beans>
<bean id="boardDAO" class="org.waterpunch.model.BoardDAOImpl"></bean>
<bean id="boardService" class="org.waterpunch.model.BoardServiceImpl">
	<constructor-arg ref="boardDAO"/>
</bean>
<beans>
public class BoardServiceImpl implements BoardService {
	private BoardDAO boardDAO;
    public BoardServiceImpl(BoardDAO boardDAO) {
    	this.boardDAO=boardDAO;
    }
}

   1-2-2 설정자(setter) 기반 의존성 주입 방식

<beans>
<bean id="boardDAO" class="org.waterpunch.model.BoardDAOImpl"></bean>
<bean id="boardService" class="org.waterpunch.model.BoardServiceImpl">
	<property name="boardDAO" ref="boardDAO"/>
</bean>
</beans>
public class BoardServiceImpl implements BoardService {
	private BoardDAO boardDAO;
    @Override
    public void setBoardDAO(BoardDAO boardDAO) {
    	this.boardDAO=boardDAO;
    }
}

 

(생성자 기반 의존성 주입방식은 xml에서 constructor-arg 이용)

(setter 기반 의존성 주입방식은 xml에서 property 이용)

 

1-3  Annotation기반 Bean 설정 방법

- Annotation 기반의 설정 방식에서는 IoC 컨테이너에 관리할 Bean을 Bean 설정 파일에 정의하는 대신 Bean을 정의하는 Annotation을 Bean의 클래스에 부여하는 방식을 사용

- 컴포넌트 스캔(Component Scan) : Annotation이 붙은 클래스를 탐색해서 IoC 컨테이너에 자동으로 등록함

                                                                      (밑에 추가 내용 있음)

- 오토와이어링(Auto Wiring) : 명시적으로 Bean을 정의하지 않고도 Annotation이 붙어 있으면

                                                         IoC 컨테이너가 자동으로 Bean을 주입하는 방식

//config.xml
//org.waterpunch 에 있는 component를 스캔한다
<context:component-scan base-package="org.waterpunch"/>
package org.waterpunch.model;

@Service
public class BankServiceImpl implements BankService {
	@Autowired
    private BankDAO BankDAO;
}

 

 

 

2. 컴포넌트 스캔 (Component Scan)

- 지정한 특정 패키지 하위의 클래스를 탐핵한 후 IoC 컨테이너에 객체 생성 후 등록함

방식 예시
XML 방식 <context:componenet-scan base-package="com.example.demo"/>
Annotation 방식 @ComponentScan(basePackages="com.example.demo")

 

2-1 컴포넌트 스캔 대상 주요 Annotation

Annotation 설명
@Controller MVC의 Controller 역할을 하는 클래스에 명시하는 Annotation
@Service 비즈니스 로직을 처리하는 클래스에 명시하는 Annotation
트랜잭션 처리는 @Service 명시 클래스에서 하도록 한다
@Repository 영속적 데이터 처리를 위한 클래스에 명시하는 Annotation
@Component 모든 컴포넌트에 대한 제네릭 스테레오 타입
위 세가지 경우에 해당하지 안흔 기타 지원 클래스에 사용

 

2-2 DI 관련 주요 Annotation

Annotation 설명
@Autowired 의존 대상 객체를 타입으로 검색해 주입
만약 동일한 타입의 객체가 여러개일 경우 NoUniqueBeanException 발생
추가적으로 @Qualifier("bean name")이 필요
@Resource @Resource : 의존 대상 객체를 타입으로 검색해 주입
@Resource(name="bean name") : 의존 대상 객체를 이름으로 검색해 주입

 

@Autowired를 해주었는데 만약 동일한 타입을 가진 bean 객체가 두 개 있다면?

 - 스프링이 어떤 빈을 주입해야 할지 알 수 없어서 스프링 컨테이너를 초기화하는 과정에서 Exception을 발생

   >> 주입은 하나를 해야하는데 실제로는 두 개 이상의 빈이 존재해 주입할 때 사용할 객체를 선택할 수 없음

   >> , @Autowired가 적용된 필드나 설정 메서드의 property 이름과 같은 이름을 가진 빈 객체가 존재할 경우

             이름이 같은 빈 객체를 주입받는다

이것을 해결하기 위해 @Qualifier 어노테이션을 사용

예시

 

@Qualifier 어노테이션

 - 사용할 의존 객체를 선택할 수 있도록 해준다

   1. 설정에서 bean의 한정자 값을 설정한다

   2. @Autowired 어노테이션이 적용된 주입 대상에 @Qualifier 어노테이션을 설정한다

      (이 때 @Qulifier 의 값으로 앞어 설정한 한정자를 사용한다

반응형

댓글