Spring@ComponentScan–フィルタータイプ
1. 概要
以前のチュートリアルでは、Springコンポーネントスキャンの基本について学習しました。
この記事では、@ComponentScanアノテーションで利用できるさまざまなタイプのフィルターオプションを紹介します。
2. @ ComponentScanフィルター
デフォルトでは、 @ Component、@ Repository、@ Service、@Controllerで注釈が付けられたクラスはSpringBeansとして登録されます。 @Componentでアノテーションが付けられたカスタムアノテーションでアノテーションが付けられたクラスについても同じことが言えます。 この動作は、@ComponentScanアノテーションのincludeFiltersおよびexcludeFiltersパラメーターを使用して拡張できます。
ComponentScan.Filterで使用できるフィルターには5つのタイプがあります。
- 注釈
- ASSIGNABLE_TYPE
- ASPECTJ
- 正規表現
- 習慣
これらについては、次のセクションで詳しく説明します。
これらのフィルターはすべて、クラスをスキャンに含めたり、スキャンから除外したりできることに注意してください。 例を簡単にするために、クラスのみを含めます。
3. FilterType.ANNOTATION
ANNOTATION フィルタータイプは、特定の注釈でマークされたコンポーネントスキャンのクラスを含めるか除外します。
たとえば、 @Animalアノテーションがあるとします。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Animal { }
それでは、@Animalを使用するElephantクラスを定義しましょう。
@Animal
public class Elephant { }
最後に、 FilterType.ANNOTATION を使用して、Springに@Animalアノテーション付きクラスをスキャンするように指示しましょう。
@Configuration
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,
classes = Animal.class))
public class ComponentScanAnnotationFilterApp { }
ご覧のとおり、スキャナーはElephantを正常に検出します。
@Test
public void whenAnnotationFilterIsUsed_thenComponentScanShouldRegisterBeanAnnotatedWithAnimalAnootation() {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(ComponentScanAnnotationFilterApp.class);
List<String> beans = Arrays.stream(applicationContext.getBeanDefinitionNames())
.filter(bean -> !bean.contains("org.springframework")
&& !bean.contains("componentScanAnnotationFilterApp"))
.collect(Collectors.toList());
assertThat(beans.size(), equalTo(1));
assertThat(beans.get(0), equalTo("elephant"));
}
4.FilterType。ASSIGNABLE_TYPE
ASSIGNABLE_TYPE は、コンポーネントスキャン中に、クラスを拡張するか、指定されたタイプのインターフェイスを実装するすべてのクラスをフィルタリングします。
まず、Animalインターフェースを宣言しましょう。
public interface Animal { }
また、 Elephant クラスを宣言しましょう。今回は、 Animal interface :を実装します。
public class Elephant implements Animal { }
Animal:も実装しているCatクラスを宣言しましょう。
public class Cat implements Animal { }
それでは、 ASSIGNABLE_TYPE を使用してSpringをガイドし、Animalをスキャンしてみましょう-クラスを実装します。
@Configuration
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
classes = Animal.class))
public class ComponentScanAssignableTypeFilterApp { }
そして、CatとElephantの両方がスキャンされることがわかります。
@Test
public void whenAssignableTypeFilterIsUsed_thenComponentScanShouldRegisterBean() {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(ComponentScanAssignableTypeFilterApp.class);
List<String> beans = Arrays.stream(applicationContext.getBeanDefinitionNames())
.filter(bean -> !bean.contains("org.springframework")
&& !bean.contains("componentScanAssignableTypeFilterApp"))
.collect(Collectors.toList());
assertThat(beans.size(), equalTo(2));
assertThat(beans.contains("cat"), equalTo(true));
assertThat(beans.contains("elephant"), equalTo(true));
}
5. FilterType.REGEX
REGEX フィルターは、クラス名が特定の正規表現パターンに一致するかどうかを確認します。 FilterType.REGEX は、単純なクラス名と完全修飾クラス名の両方をチェックします。
もう一度、Elephantクラスを宣言しましょう。 今回は、インターフェイスを実装していないか、注釈が付けられていません:
public class Elephant { }
もう1つのクラスCatを宣言しましょう。
public class Cat { }
それでは、Loinクラスを宣言しましょう。
public class Loin { }
使ってみよう FilterType 。 正規表現 Springに正規表現に一致するクラスをスキャンするように指示します
@Configuration
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.REGEX,
pattern = ".*[nt]"))
public class ComponentScanRegexFilterApp { }
今回のテストでは、Springが Elephant をスキャンしますが、 Lion :はスキャンしません。
@Test
public void whenRegexFilterIsUsed_thenComponentScanShouldRegisterBeanMatchingRegex() {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(ComponentScanRegexFilterApp.class);
List<String> beans = Arrays.stream(applicationContext.getBeanDefinitionNames())
.filter(bean -> !bean.contains("org.springframework")
&& !bean.contains("componentScanRegexFilterApp"))
.collect(Collectors.toList());
assertThat(beans.size(), equalTo(1));
assertThat(beans.contains("elephant"), equalTo(true));
}
6. FilterType.ASPECTJ
式を使用してクラスの複雑なサブセットを選択する場合は、 FilterType ASPECTJを使用する必要があります。
このユースケースでは、前のセクションと同じ3つのクラスを再利用できます。
FilterType.ASPECTJ を使用して、SpringにAspectJ式に一致するクラスをスキャンするように指示しましょう。
@Configuration
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ASPECTJ,
pattern = "com.baeldung.componentscan.filter.aspectj.* "
+ "&& !(com.baeldung.componentscan.filter.aspectj.L* "
+ "|| com.baeldung.componentscan.filter.aspectj.C*)"))
public class ComponentScanAspectJFilterApp { }
少し複雑ですが、ここでのロジックでは、クラス名に「L」も「C」も含まないBeanが必要であるため、Elephantが再び残ります。
@Test
public void whenAspectJFilterIsUsed_thenComponentScanShouldRegisterBeanMatchingAspectJCreteria() {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(ComponentScanAspectJFilterApp.class);
List<String> beans = Arrays.stream(applicationContext.getBeanDefinitionNames())
.filter(bean -> !bean.contains("org.springframework")
&& !bean.contains("componentScanAspectJFilterApp"))
.collect(Collectors.toList());
assertThat(beans.size(), equalTo(1));
assertThat(beans.get(0), equalTo("elephant"));
}
7. FilterType.CUSTOM
上記のフィルタータイプのいずれも要件を満たしていない場合は、
カスタムフィルターを作成するには、org.springframework.core.type.filter.TypeFilterを実装する必要があります。
public class ComponentScanCustomFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
ClassMetadata classMetadata = metadataReader.getClassMetadata();
String fullyQualifiedName = classMetadata.getClassName();
String className = fullyQualifiedName.substring(fullyQualifiedName.lastIndexOf(".") + 1);
return className.length() > 5 ? true : false;
}
}
FilterType。CUSTOMを使用して、カスタムフィルター ComponentScanCustomFilter:を使用してSpringをスキャンクラスに伝達します。
@Configuration
@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.CUSTOM,
classes = ComponentScanCustomFilter.class))
public class ComponentScanCustomFilterApp { }
次に、カスタムフィルター ComponentScanCustomFilter:のテストケースを見てみましょう。
@Test
public void whenCustomFilterIsUsed_thenComponentScanShouldRegisterBeanMatchingCustomFilter() {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(ComponentScanCustomFilterApp.class);
List<String> beans = Arrays.stream(applicationContext.getBeanDefinitionNames())
.filter(bean -> !bean.contains("org.springframework")
&& !bean.contains("componentScanCustomFilterApp")
&& !bean.contains("componentScanCustomFilter"))
.collect(Collectors.toList());
assertThat(beans.size(), equalTo(1));
assertThat(beans.get(0), equalTo("elephant"));
}
8. 概要
このチュートリアルでは、@ComponentScan。に関連付けられたフィルターを紹介しました
いつものように、完全なコードはGitHubでから入手できます。