Saya memiliki komponen yang ingin saya kecualikan dari a @ComponentScan
secara khusus @Configuration
:
@Component("foo") class Foo {
...
}
Jika tidak, sepertinya akan bentrok dengan kelas lain dalam proyek saya. Saya tidak sepenuhnya memahami tabrakan, tetapi jika saya mengomentari @Component
anotasi, semuanya berfungsi seperti yang saya inginkan. Tetapi proyek lain yang mengandalkan pustaka ini mengharapkan kelas ini dikelola oleh Spring, jadi saya ingin melewatkannya hanya di proyek saya.
Saya mencoba menggunakan @ComponentScan.Filter
:
@Configuration
@EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}
tetapi tampaknya tidak berhasil. Jika saya mencoba menggunakan FilterType.ASSIGNABLE_TYPE
, saya mendapatkan kesalahan aneh tentang tidak dapat memuat beberapa kelas yang tampaknya acak:
Disebabkan oleh: java.io.FileNotFoundException: sumber daya jalur kelas [junit / framework / TestCase.class] tidak dapat dibuka karena tidak ada
Saya juga mencoba menggunakan type=FilterType.CUSTOM
sebagai berikut:
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 {}
Tapi sepertinya itu tidak mengecualikan komponen dari pemindaian seperti yang saya inginkan.
Bagaimana cara mengecualikannya?
sumber
Menggunakan tipe eksplisit dalam filter pindai jelek bagi saya. Saya percaya pendekatan yang lebih elegan adalah membuat anotasi marker sendiri:
@Retention(RetentionPolicy.RUNTIME) public @interface IgnoreDuringScan { }
Tandai komponen yang harus dikecualikan dengannya:
@Component("foo") @IgnoreDuringScan class Foo { ... }
Dan kecualikan anotasi ini dari pemindaian komponen Anda:
@ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class)) public class MySpringConfiguration {}
sumber
@Component
, tapi saya rasa bukan itu pertanyaannyaPendekatan lain adalah dengan menggunakan anotasi bersyarat baru. Sejak polos Spring bintang 4 Anda dapat menggunakan penjelasan @Conditional:
@Component("foo") @Conditional(FooCondition.class) class Foo { ... }
dan tentukan logika kondisional untuk mendaftarkan komponen Foo:
public class FooCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // return [your conditional logic] } }
Logika bersyarat dapat didasarkan pada konteks, karena Anda memiliki akses ke pabrik kacang. Sebagai Contoh ketika komponen "Bar" tidak terdaftar sebagai kacang:
return !context.getBeanFactory().containsBean(Bar.class.getSimpleName());
Dengan Spring Boot (sebaiknya digunakan untuk SETIAP project Spring baru), Anda dapat menggunakan anotasi bersyarat berikut:
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnExpression
@ConditionalOnJava
@ConditionalOnMissingBean
@ConditionalOnMissingClass
@ConditionalOnNotWebApplication
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication
Anda dapat menghindari pembuatan kelas Kondisi dengan cara ini. Lihat dokumen Spring Boot untuk detail selengkapnya.
sumber
Jika Anda perlu menentukan dua atau lebih kriteria excludeFilters , Anda harus menggunakan array.
Untuk contoh di bagian kode ini saya ingin mengecualikan semua kelas di paket org.xxx.yyy dan kelas khusus lainnya, MyClassToExclude
@ComponentScan( excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.xxx.yyy.*"), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyClassToExclude.class) })
sumber
Saya mengalami masalah saat menggunakan @Configuration , @EnableAutoConfiguration , dan @ComponentScan ketika mencoba untuk mengecualikan kelas konfigurasi tertentu, hal itu tidak bekerja!
Akhirnya saya memecahkan masalah dengan menggunakan @SpringBootApplication , yang menurut dokumentasi Spring melakukan fungsi yang sama seperti tiga di atas dalam satu anotasi.
Tip lainnya adalah mencoba terlebih dahulu tanpa menyempurnakan pemindaian paket Anda (tanpa filter basePackages).
@SpringBootApplication(exclude= {Foo.class}) public class MySpringConfiguration {}
sumber
Dalam hal mengecualikan komponen pengujian atau konfigurasi pengujian, Spring Boot 1.4 memperkenalkan anotasi pengujian baru
@TestComponent
dan@TestConfiguration
.sumber
Saya perlu mengecualikan @Aspect @Component audit dari konteks aplikasi tetapi hanya untuk beberapa kelas pengujian. Saya akhirnya menggunakan @Profile ("audit") di kelas aspek; menyertakan profil untuk operasi normal tetapi mengecualikannya (jangan letakkan di @ActiveProfiles) pada kelas pengujian tertentu.
sumber