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);
//新增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一起使用,它可以根据一定的规则扫描类路径下满足特定条件的Class来作为候选的bean定义。它在扫描时可以通过TypeFilter来指定需要匹配的类和需要排除的类,使用ClassPathScanningCandidateComponentProvider时可以通过构造参数useDefaultFilter指定是否需要使用默认的TypeFilter,默认的TypeFilter将包含类上拥有 @Component、@Service、@Repository、@Controller、@javax.annotation.ManagedBean和@javax.inject.Named注解的类。在扫描时需要指定扫描的根包路径。以下是一些使用ClassPathScanningCandidateComponentProvider扫描并注册bean定义的示例。
扫描指定包及其子包下面的所有非接口和非抽象类:
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
boolean useDefaultFilters = false;//是否使用默认的filter,使用默认的filter意味着只扫描那些类上拥有Component、Service、Repository或Controller注解的类。
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<BeanDefinition> beanDefinitions = beanScanner.findCandidateComponents(basePackage);
for (BeanDefinition beanDefinition : beanDefinitions) {
//beanName通常由对应的BeanNameGenerator来生成,比如Spring自带的AnnotationBeanNameGenerator、DefaultBeanNameGenerator等,也可以自己实现。
String beanName = beanDefinition.getBeanClassName();
registry.registerBeanDefinition(beanName, beanDefinition);
}
}
扫描指定包及其子包下面拥有指定注解的类:
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
boolean useDefaultFilters = false;//是否使用默认的filter,使用默认的filter意味着只扫描那些类上拥有Component、Service、Repository或Controller注解的类。
String basePackage = "com.elim.learn.spring.bean";
ClassPathScanningCandidateComponentProvider beanScanner = new ClassPathScanningCandidateComponentProvider(useDefaultFilters);
TypeFilter includeFilter = new AnnotationTypeFilter(HelloAnnotation.class);
beanScanner.addIncludeFilter(includeFilter);
Set<BeanDefinition> beanDefinitions = beanScanner.findCandidateComponents(basePackage);
for (BeanDefinition beanDefinition : beanDefinitions) {
//beanName通常由对应的BeanNameGenerator来生成,比如Spring自带的AnnotationBeanNameGenerator、DefaultBeanNameGenerator等,也可以自己实现。
String beanName = beanDefinition.getBeanClassName();
registry.registerBeanDefinition(beanName, beanDefinition);
}
}
AnnotationTypeFilter是Spring自带的一个TypeFilter,可以扫描指定的注解。AnnotationTypeFilter一共有三个构造方法,主要差别在于considerMetaAnnotations和considerInterfaces 代码如下:
public AnnotationTypeFilter(Class<? extends Annotation> annotationType) {
this(annotationType, true, false);
}
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) {
this(annotationType, considerMetaAnnotations, false);
}
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations, boolean considerInterfaces) {
super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces);
this.annotationType = annotationType;
this.considerMetaAnnotations = considerMetaAnnotations;
}
指定considerMetaAnnotations="true"时则如果目标类上没有指定的注解,但是目标类上的某个注解中存在了指定的注解则该类也将匹配。
指定considerInterfaces="true"时,则如果对应的类的上层接口上拥有指定的注解时也将匹配。比如A是B的实现类,B为Interface,A为Class,A implements B,B中有对应的注解,这样A也会被扫描到;
如果我们需要扫描的目标注解上是加了@Inherited注解的,则如果一个类上没有指定的目标注解,但是其父类拥有对应的注解,则也会被扫描到。
AssignableTypeFilter也是Spring内置的一个TypeFilter,用于扫描指定类型的类。只要目标类型能够赋值给指定的类型,则表示匹配。即如果指定的是一个接口,则所有直接或间接实现该接口的类都将被扫描到。
欢迎加入作者的微信公众号:
本文是转载加上作者修改而来,非原创!