케네스로그

[스프링] 컴포논트 스캔 @ComponentScan 본문

Dev/스프링

[스프링] 컴포논트 스캔 @ComponentScan

kenasdev 2022. 4. 25. 23:16
반응형

컴포넌트 스캔은 스프링이 직접 클래스를 검색해서 빈으로 등록해주는 기능을 말한다. 이 컴포넌트 스캔 기능을 통해서 설정 클래스에서 빈으로 등록하지 않고, 클래스 정의에 @Component 애노테이션을 통해 빈으로 등록할 수 있다.

 

컴포넌트

@Component 애노테이션을 통해 클래스를 정의하면 빈으로 등록된다. 이 때, 아래와 같이 빈 이름을 부여할 수 있고, 정의하지 않으면 자동으로 앞글자는 소문자로 하여 등록된다.

@Component("forTest")
public class TestClass() { }

@Component // automadeClass
public class AutomadeClass() { }

 

 

@ComponentScan 애노테이션과 컴포넌트 스캔

@Component 애노테이션을 통해 빈 등록을 위해서는 설정 클래스에서 @ComponentScan 애노테이션을 사용해야 한다.

 

@Configuration
@ComponentScan(basePackage={"spring"})
public class AppCtx {
		...
}

basePackage속성을 통해서 스캔 대상 패키지 목록을 지정할 수 있다. 위의 코드에서는 spring 패키지와 그 하위 패키지에 속한 클래스들을 모두 스캔 대상으로 설정한다. 해당 범위의 클래스들 중 @Component 애노테이션이 붙은 클래스는 빈으로 등록된다.

 

스캔 대상에서 제외/포함 시키기

@Configuration
@ComponentScan(basePackage={"spring"}),
	excludeFilters = @Filter(type=FilterType.REGEX, pattern="spring||..*DAO"))
public class AppCtxWithExclude() { 
	...
}

@Filter 애노테이션의 속성으로 type과 pattern을 통해서 제외 또는 포함시킬 수 있다. 위의 예제 코드에서는 FilterType.REGEX를 통해 정규표현식으로 패턴을 정의했다. pattern은 FilterType.ASPECTJ를 필터 타입으로도 설정할 수 있는데, 정규표현식 대신 AspectJ패턴을 사용하면 다음과 같다.

@Configuration
@ComponentScan(basePackage={"spring"}),
	excludeFilters = @Filter(type=FilterType.ASPECTJ, pattern="spring.*Dao"))
public class AppCtxWithExclude() { 
	...
}

 

기본 스캔 대상

@Component 클래스 뿐 만 아니라 sterotype패키지에 속하는 아래의 애노테이션도 스캔 대상에 포함된다. 

  • @Component
  • @Controller
  • @Service
  • @Repository
  • @Aspect
  • @Configuration

Aspect를 제외한 나머지 애노테이션들은 내부에 @Component를 포함하는 특수 애노테이션이다.

 

컴포넌트 스캔과 충돌

컴포넌트 스캔을 통해 빈을 등록하는 과정에서 충돌이 발생하는 경우가 있다. 그런 경우는 자동 또는 수동으로 등록되는 빈 중에 이름이 겹쳐서 발생하게 된다.

 

스캔 중 자동 등록으로 인한 충돌

// in spring package A
@Component
public class MemberDao {
	...
}

// in spring package B
@Component
public class MemberDao {
	...
}

다른 패키지에 같은 컴포넌트 클래스가 존재하면, 스프링은 같은 이름으로 2개의 빈이 등록되기 때문에 에러를 발생시킨다.

 

수동 등록으로 인한 충돌

@Component
public class MemberDao {
	...
}

@Bean
public MemberDao memberDao {
	return new MemberDao();
}

위의 경우, @Component 애노테이션을 통해 자동으로 빈을 등록하고, 동시에 @Bean 애노테이션을 통해 같은 이름으로 빈을 등록한다. 이러한 경우 수동으로 빈을 등록하였지만, 이름이 겹치기때문에 충돌이 발생하게 된다.

 

 

 

반응형