@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 2018

@Bashar Ali Labadi、この構成のそのようなポイントではありませんか?すべてのコンポーネントスキャンから除外する場合は、Springコンポーネントであってはなりません。
luboskrnac

30

別のアプローチは、新しい条件付き注釈を使用することです。プレーンなSpring4以降、@ 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]
    }     
}

Beanファクトリにアクセスできるため、条件付きロジックはコンテキストに基づくことができます。たとえば、「Bar」コンポーネントがBeanとして登録されていない場合:

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

Spring Boot(すべての新しいSpringプロジェクトに使用する必要があります)では、次の条件付きアノテーションを使用できます。

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

この方法で、Conditionクラスの作成を回避できます。詳細については、SpringBootのドキュメントを参照してください。


1
条件文の+1、これはフィルターを使用するよりもはるかにクリーンな方法です。Beanの条件付きロードほど一貫して機能するフィルターを取得したことはありません
wondergoat77 2017

13

2つ以上の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を使用すると問題が発生しましたが機能しませんでした。

最終的に、@ SpringBootApplicationを使用して問題を解決しました。これは、Springのドキュメントによると、1つのアノテーションで上記の3つと同じ機能を実行します。

もう1つのヒントは、パッケージスキャンを調整せずに(basePackagesフィルターなしで)最初に試すことです。

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

これを試しましたが、「次のクラスは自動構成クラスではないため、除外できませんでした」というエラーが表示されます。@ComponentScanを使用したexcludeFiltersは正常に機能しています。
AzarEJ


0

監査@ Aspect @ Componentをアプリコンテキストから除外する必要がありましたが、いくつかのテストクラスのみが対象でした。アスペクトクラスで@Profile( "audit")を使用することになりました。通常の操作のプロファイルを含めますが、特定のテストクラスでは除外します(@ActiveProfilesには入れないでください)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.