@ComponentScan에서 @Component 제외


90

@ComponentScan특정에서 제외하려는 구성 요소가 있습니다 @Configuration.

@Component("foo") class Foo {
...
}

그렇지 않으면 내 프로젝트의 다른 클래스와 충돌하는 것 같습니다. 충돌을 완전히 이해하지는 못하지만 @Component주석을 달면 원하는대로 작동합니다. 그러나이 라이브러리에 의존하는 다른 프로젝트는이 클래스가 Spring에서 관리 될 것으로 예상하므로 내 프로젝트에서만 건너 뛰고 싶습니다.

나는 사용해 보았다 @ComponentScan.Filter:

@Configuration 
@EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
  @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}

하지만 작동하지 않는 것 같습니다. 을 사용하려고하면 FilterType.ASSIGNABLE_TYPE임의의 클래스를로드 할 수 없다는 이상한 오류가 발생합니다.

원인 : java.io.FileNotFoundException : 클래스 경로 리소스 [junit / framework / TestCase.class]가 존재하지 않기 때문에 열 수 없습니다.

또한 type=FilterType.CUSTOM다음과 같이 사용해 보았습니다 .

class ExcludeFooFilter implements TypeFilter {
    @Override
    public boolean match(MetadataReader metadataReader,
            MetadataReaderFactory metadataReaderFactory) throws IOException {
        return metadataReader.getClass() == Foo.class;
    }
}

@Configuration @EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
  @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}

그러나 그것은 내가 원하는 것처럼 스캔에서 구성 요소를 제외하지 않는 것 같습니다.

어떻게 제외합니까?

답변:


107

excludeFilters대신 다음을 사용해야한다는 점을 제외하면 구성이 괜찮아 보입니다 excludes.

@Configuration @EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
  @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}

죄송합니다. 잘라 내기 및 붙여 넣기 오류였습니다. excludeFilters를 사용하고 있습니다. 나는 또 다른 모습이 나를 정말 기괴한주는 오류를 ... 할게요
ykaganovich

52

스캔 필터에서 명시 적 유형을 사용하는 것은 나에게 좋지 않습니다. 더 우아한 접근 방식은 자체 마커 주석을 만드는 것입니다.

@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreDuringScan {
}

제외해야하는 구성 요소를 표시하십시오.

@Component("foo") 
@IgnoreDuringScan
class Foo {
    ...
}

구성 요소 스캔에서이 주석을 제외합니다.

@ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class))
public class MySpringConfiguration {}

13
프로젝트에서 응용 프로그램 컨텍스트의 하위 집합에서만 구성 요소를 제외하려는 경우에는 도움이되지 않지만 범용 제외에 대한 영리한 아이디어입니다. 정말로, 그것을 보편적으로 배제하기 위해 @Component, 그냥 제거 할 수 있습니다 . 그러나 저는 그것이 질문이 요구하는 것이라고 생각하지 않습니다
Kirby

2
같은 필터가없는 다른 구성 요소 스캔 주석 어딘가에있는 경우이 작동하지 않습니다
바샤 르 알리 라 바디

@Bashar Ali Labadi,이 구조의 포인트가 아닌가요? 모든 구성 요소 스캔에서 제외하려면 아마도 Spring 구성 요소가 아니어야합니다.
luboskrnac

30

또 다른 접근 방식은 새로운 조건부 주석을 사용하는 것입니다. 평범한 Spring 4 부터 @Conditional 주석을 사용할 수 있습니다.

@Component("foo")
@Conditional(FooCondition.class)
class Foo {
    ...
}

Foo 구성 요소를 등록하기위한 조건부 논리를 정의합니다.

public class FooCondition implements Condition{
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // return [your conditional logic]
    }     
}

빈 팩토리에 액세스 할 수 있으므로 조건부 논리는 컨텍스트를 기반으로 할 수 있습니다. 예를 들어 "Bar"컴포넌트가 Bean으로 등록되지 않은 경우 :

    return !context.getBeanFactory().containsBean(Bar.class.getSimpleName());

Spring Boot (모든 새로운 Spring 프로젝트에 사용되어야 함)를 사용하면 다음과 같은 조건부 주석을 사용할 수 있습니다.

  • @ConditionalOnBean
  • @ConditionalOnClass
  • @ConditionalOnExpression
  • @ConditionalOnJava
  • @ConditionalOnMissingBean
  • @ConditionalOnMissingClass
  • @ConditionalOnNotWebApplication
  • @ConditionalOnProperty
  • @ConditionalOnResource
  • @ConditionalOnWebApplication

이런 식으로 Condition 클래스 생성을 피할 수 있습니다. 자세한 내용은 Spring Boot 문서를 참조하십시오.


1
조건부 +1은 필터를 사용하는 것보다 훨씬 더 깔끔한 방법입니다. 나는 이제까지 조건 콩의 로딩으로 지속적으로 작업에 필터를 못 했어
wondergoat77

13

둘 이상의 excludeFilters 기준 을 정의해야하는 경우 배열을 사용해야합니다.

이 코드 섹션의 인스턴스의 경우 org.xxx.yyy 패키지 의 모든 클래스 와 다른 특정 클래스 인 MyClassToExclude 를 제외하고 싶습니다.

 @ComponentScan(            
        excludeFilters = {
                @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.xxx.yyy.*"),
                @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyClassToExclude.class) })

이 정규식은 "org.xxx.yyyy.z"와도 일치하기 때문에 ASPECTJ를 필터 유형으로 제안합니다
wutzebaer

9

@Configuration , @EnableAutoConfiguration@ComponentScan 을 사용할 때 특정 구성 클래스를 제외하려고 할 때 문제가 발생했지만 작동하지 않았습니다!

결국 나는 Spring 문서에 따르면 하나의 주석에서 위의 세 가지와 동일한 기능을 수행하는 @SpringBootApplication 을 사용하여 문제를 해결했습니다 .

또 다른 팁은 패키지 스캔을 수정하지 않고 (basePackages 필터없이) 먼저 시도하는 것입니다.

@SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}

나는 이것을 시도했지만 "다음 클래스는 자동 구성 클래스가 아니기 때문에 제외 할 수 없습니다"라는 오류를 표시합니다. @ComponentScan을 사용하는 excludeFilters가 제대로 작동합니다.
AzarEJ


0

앱 컨텍스트에서 감사 @Aspect @Component를 제외해야했지만 몇 가지 테스트 클래스에 대해서만 필요했습니다. 나는 aspect 클래스에서 @Profile ( "audit")을 사용하게되었다. 일반 작업에 대한 프로필을 포함하지만 특정 테스트 클래스에서 제외합니다 (@ActiveProfiles에 넣지 마십시오).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.