@Component'i @ComponentScan'den hariç tut


90

Ben çıkarmak istediğiniz bir bileşene sahip @ComponentScanbir özellikle @Configuration:

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

Aksi takdirde, projemdeki başka bir sınıfla çatışıyor gibi görünüyor. Çarpışmayı tam olarak anlamıyorum, ancak @Componentek açıklamayı yorumlarsam işler istediğim gibi çalışır. Ancak bu kitaplığa dayanan diğer projeler bu sınıfın Spring tarafından yönetilmesini bekliyor, bu yüzden onu sadece projemde atlamak istiyorum.

Kullanmayı denedim @ComponentScan.Filter:

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

ama işe yaramıyor gibi görünüyor. Kullanmayı FilterType.ASSIGNABLE_TYPEdenersem, rastgele görünen bazı sınıfları yükleyememe konusunda garip bir hata alıyorum:

Neden olduğu: java.io.FileNotFoundException: sınıf yolu kaynağı [junit / framework / TestCase.class], mevcut olmadığı için açılamıyor

Ayrıca type=FilterType.CUSTOMaşağıdaki gibi kullanmayı da denedim :

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

Ancak bu, bileşeni istediğim gibi taramanın dışında bırakmıyor gibi görünüyor.

Nasıl hariç tutabilirim?

Yanıtlar:


108

Yapılandırma iyi görünüyor, ancak bunun excludeFiltersyerine şunu kullanmanız gerekir excludes:

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

üzgünüm, bu bir kes ve yapıştır hatasıydı. ExcludeFilters kullanıyorum. Bir kez daha bakacağım, bunun bana verdiği hata gerçekten tuhaf ...
— ykaganovich

53

Tarama filtrelerinde açık türler kullanmak benim için çirkin. Daha zarif bir yaklaşımın kendi işaretçi ek açıklamasını oluşturmak olduğuna inanıyorum:

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

Hariç tutulması gereken bileşeni işaretleyin:

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

Ve bu ek açıklamayı bileşen taramanızın dışında tutun:

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

13
Bu, evrensel dışlama için akıllıca bir fikir olsa da, bir bileşeni bir projedeki uygulama bağlamlarının yalnızca bir alt kümesinden dışlamak istiyorsanız yardımcı olmayacaktır. Gerçekten, evrensel olarak dışlamak için, sadece kaldırılabilir @Component, ancak sorunun sorulduğunu sanmıyorum
— Kirby

2
Aynı filtreye sahip olmayan bir yerde başka bir bileşen tarama ek açıklamanız varsa bu işe yaramaz
— Bashar Ali Labadi

@Bashar Ali Labadi, bu yapının amacı bu değil mi? Tüm bileşen taramalarından hariç tutmak istiyorsanız, muhtemelen hiç Spring bileşeni olmamalıdır.
— luboskrnac

30

Diğer bir yaklaşım, yeni koşullu ek açıklamalar kullanmaktır. Düz İlkbahar 4'ten beri @ Koşullu ek açıklamayı kullanabilirsiniz:

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

ve Foo bileşenini kaydetmek için koşullu mantığı tanımlayın:

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

Fasulye fabrikasına erişiminiz olduğu için koşullu mantık bağlama dayalı olabilir. Örneğin, "Bar" bileşeni fasulye olarak kaydedilmediğinde:

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

Spring Boot ile (HER yeni Bahar projesinde kullanılmalıdır), şu koşullu ek açıklamaları kullanabilirsiniz:

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

Bu şekilde Koşul sınıfı oluşturmanın önüne geçebilirsiniz. Daha fazla ayrıntı için Spring Boot belgelerine bakın.


1
Koşullar için +1, bu benim için filtre kullanmaktan çok daha temiz bir yol. Fasulyelerin koşullu yüklenmesi kadar tutarlı bir şekilde çalışacak filtrelerim
— olmadı

13

İki veya daha fazla excludeFilters tanımlamanız gerekirse ölçütü , diziyi kullanmanız gerekir.

Kodun bu bölümündeki örnekler için org.xxx.yyy paketindeki tüm sınıfları ve başka bir belirli sınıf olan MyClassToExclude'ı hariç tutmak istiyorum

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

ASPECTJ'i filtre türü olarak öneririm, çünkü bu normal ifade "org.xxx.yyyy.z" ile de eşleşir
— wutzebaer

9

Kullanırken bir sorun vardı @Configuration , @EnableAutoConfiguration ve @ComponentScan özgü konfigürasyon sınıflarını hariç çalışırken, şey, iş vermedi olduğunu!

Sonunda sorunu @SpringBootApplication kullanarak çözdüm , Spring belgelerine göre yukarıdaki üç ile aynı işlevselliği bir açıklamada yapan .

Başka bir İpucu da paket taramanızı iyileştirmeden denemektir (temel Paketler filtresi olmadan).

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

1
Bunu denedim, ancak "Aşağıdaki sınıflar otomatik yapılandırma sınıfları olmadıkları için dışlanamadı" şeklinde hata gösteriyorum. @ComponentScan ile excludeFilters düzgün çalışıyor.
— AzarEJ


0

@Aspect @Component denetimini uygulama bağlamından hariç tutmam gerekti, ancak yalnızca birkaç test sınıfı için. En boy sınıfında @Profile ("denetim") kullanmaya başladım; normal işlemler için profil dahil ancak hariç (@ActiveProfiles içine koymayın) belirli test sınıflarında.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.