カスタムBeanDefinitionRegistryPostProcessor



Custom Beandefinitionregistrypostprocessor



BeanDefinitionRegistryPostProcessorは、BeanFactoryPostProcessorを継承し、特別なBeanFactoryPostProcessorです。 BeanDefinitionRegistryPostProcessorで定義postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)このメソッドを使用すると、カスタム登録されたBean定義のロジックを実装できます。次の例では、タイプTestBeanのtestBeanという名前の新しいBean定義が定義されています。

public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { RootBeanDefinition testBean = new RootBeanDefinition(TextBean.class) //Add BeanDefiniton registry.registerBeanDefinition('test', testBean) } }
  • テストで使用される構成はJavaクラス構成に基づいており、対応する構成クラスは次のとおりです。
@Configuration public class SpringConfiguration { @Bean public CustomBeanDefinitionRegistry customBeanDefinitionRegistry() { return new CustomBeanDefinitionRegistry() } }
  • テストは次のとおりです。
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={SpringConfiguration.class}) public class CustomBeanDefinitionRegistryTest { @Autowired private TestBean testBean @Test public void test() { Assert.assertNotNull(testBean) } }
  • ClassPathScanningCandidateComponentProvider

カスタムBeanDefinitionRegistryPostProcessorを使用してカスタムBean定義を追加する場合、ClassPathScanningCandidateComponentProviderと一緒に使用できます。特定のルールに従って、候補Bean定義として、クラスパスの下で特定の条件を満たすクラスをスキャンできます。 TypeFilterを使用して、スキャン時に照合するクラスと除外するクラスを指定できます。 ClassPathScanningCandidateComponentProviderを使用する場合、構成パラメーターuseDefaultFilterを使用して、デフォルトパラメーターTypeFilterを使用できます。デフォルトのTypeFilterには、クラスに@ Component、@ Service、@が含まれます。リポジトリ、@ Controller、@ javax.annotation.ManagedBean、および@ javax.inject.Namedアノテーション付きクラス。スキャンするときは、スキャンのルートパケットパスを指定する必要があります。 ClassPathScanningCandidateComponentProviderを使用してBean定義をスキャンおよび登録する例を次に示します。



指定されたパッケージとそのサブパッケージの下にあるすべての非インターフェイスクラスと非抽象クラスをスキャンします。

@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Boolean useDefaultFilters = false//Whether the default filter is used, using the default filter means scanning only those classes that have Component, Service, Repository, or Controller annotations on those classes. String basePackage = 'com.elim.learn.spring.bean' ClassPathScanningCandidateComponentProvider beanScanner = new ClassPathScanningCandidateComponentProvider(useDefaultFilters) TypeFilter includeFilter = new TypeFilter() { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { return metadataReader.getClassMetadata().isConcrete() } } beanScanner.addIncludeFilter(includeFilter) Set beanDefinitions = beanScanner.findCandidateComponents(basePackage) for (BeanDefinition beanDefinition : beanDefinitions) { //beanName is usually generated by the corresponding BeanNameGenerator, such as Spring's own AnnotationBeanNameGenerator, DefaultBeanNameGenerator, etc., can also be implemented by themselves. String beanName = beanDefinition.getBeanClassName() registry.registerBeanDefinition(beanName, beanDefinition) } }

以下の指定された注釈を使用して、指定されたパッケージとそのサブパッケージをスキャンします。



@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { Boolean useDefaultFilters = false//Whether the default filter is used, using the default filter means scanning only those classes that have Component, Service, Repository, or Controller annotations on those classes. String basePackage = 'com.elim.learn.spring.bean' ClassPathScanningCandidateComponentProvider beanScanner = new ClassPathScanningCandidateComponentProvider(useDefaultFilters) TypeFilter includeFilter = new AnnotationTypeFilter(HelloAnnotation.class) beanScanner.addIncludeFilter(includeFilter) Set beanDefinitions = beanScanner.findCandidateComponents(basePackage) for (BeanDefinition beanDefinition : beanDefinitions) { //beanName is usually generated by the corresponding BeanNameGenerator, such as Spring's own AnnotationBeanNameGenerator, DefaultBeanNameGenerator, etc., can also be implemented by themselves. String beanName = beanDefinition.getBeanClassName() registry.registerBeanDefinition(beanName, beanDefinition) } }

AnnotationTypeFilterは、Springに付属し、指定された注釈をスキャンできるTypeFilterです。 AnnotationTypeFilterには3つの構築メソッドがありますが、主な違いは thinkMetaAnnotationsthinkInterfaces コードは次のように表示されます。

public AnnotationTypeFilter(Class annotationType) { this(annotationType, true, false) } public AnnotationTypeFilter(Class annotationType, boolean considerMetaAnnotations) { this(annotationType, considerMetaAnnotations, false) } public AnnotationTypeFilter(Class annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) { super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces) this.annotationType = annotationType this.considerMetaAnnotations = considerMetaAnnotations }

specifiederMetaAnnotations = 'true'が指定されている場合、ターゲットクラスにアノテーションが指定されていないが、指定されたアノテーションがターゲットクラスのアノテーションに存在する場合、クラスも一致します。

consoleInterfaces = 'true'が指定されている場合、対応するクラスの上位インターフェイスに指定されたアノテーションがある場合にも一致します。たとえば、AはBの実装クラス、Bはインターフェイス、Aはクラス、AはBを実装し、Bには対応するアノテーションがあるため、Aもスキャンされます。



スキャンする必要のあるターゲットアノテーションが@AliExpressアノテーションでマークされている場合、クラスにターゲットアノテーションが指定されていないが、その親に対応するアノテーションがある場合は、それもスキャンされます。

AssignableTypeFilterは、指定されたタイプのクラスをスキャンするためにSpringに組み込まれているTypeFilterでもあります。ターゲットタイプを指定されたタイプに割り当てることができる限り、一致が示されます。つまり、インターフェイスが指定されている場合、インターフェイスを直接または間接的に実装するすべてのクラスがスキャンされます。

この記事は、オリジナルではなく、作者の修正を加えて複製されています。