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