[java] @ComponentScan에서 @Component 제외

@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 {}

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

어떻게 제외합니까?



답변

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

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


답변

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

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

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

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

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

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


답변

또 다른 접근 방식은 새로운 조건부 주석을 사용하는 것입니다. 평범한 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 문서를 참조하십시오.


답변

둘 이상의 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) })


답변

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

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

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

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


답변

테스트 구성 요소 또는 테스트 구성을 제외하는 경우 Spring Boot 1.4는 새로운 테스트 주석 @TestComponent@TestConfiguration .


답변

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