ImportBeanDefinitionRegistrar用法

Spring官方通过ImportBeanDefinitionRegistrar实现了@Component、@Service等注解的动态注入机制。

很多三方框架集成Spring的时候,都会通过该接口,实现扫描指定的类,然后注册到spring容器中。 比如Mybatis中的Mapper接口,springCloud中的FeignClient接口,都是通过该接口实现的自定义注册逻辑。

所有实现了该接口的类的都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化,也能被aop、validator等机制处理。

基本步骤:
实现ImportBeanDefinitionRegistrar接口;
通过registerBeanDefinitions实现具体的类初始化;
在@Configuration注解的配置类上使用@Import导入实现类;

简单示例
这里实现一个非常简单的操作,自定义一个@Mapper注解(并非Mybatis中的Mapper实现),实现类似@Component的功能,添加了@Mapper注解的类会被自动加载到spring容器中。

首先创建@Mapper注解。

@Documented
@Inherited 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) 
public @interface Mapper { 
}

创建UserMapper类,用于使用@Mapper注。

@Mapper
public class UserMapper {
}

定义ImportBeanDefinitionRegistrar的实现类MapperAutoConfigureRegistrar。如果需要获取Spring中的一些数据,可实现一些Aware接口,这实现了ResourceLoaderAware。

public class MapperAutoConfigureRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    
    private ResourceLoader resourceLoader;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        MapperBeanDefinitionScanner scanner = new MapperBeanDefinitionScanner(registry, false);
        scanner.setResourceLoader(resourceLoader);
        scanner.registerFilters();
        scanner.addIncludeFilter(new AnnotationTypeFilter(Mapper.class));
        scanner.doScan("com.secbro2.learn.mapper");
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

在上面代码中,通过ResourceLoaderAware接口的setResourceLoader方法获得到了ResourceLoader对象。
在registerBeanDefinitions方法中,借助ClassPathBeanDefinitionScanner类的实现类来扫描获取需要注册的Bean。

MapperBeanDefinitionScanner的实现如下:

public class MapperBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {

    public MapperBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
        super(registry, useDefaultFilters);
    }

    protected void registerFilters() {
        addIncludeFilter(new AnnotationTypeFilter(Mapper.class));
    }

    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        return super.doScan(basePackages);
    }
}

MapperBeanDefinitionScanner继承子ClassPathBeanDefinitionScanner,扫描被@Mapper的注解的类。
在MapperBeanDefinitionScanner中指定了addIncludeFilter方法的参数为包含Mapper的AnnotationTypeFilter
当然也可以通过excludeFilters指定不加载的类型。这两个方法由它们的父类ClassPathScanningCandidateComponentProvider提供的。

完成了上面的定义,则进行最后一步引入操作了。创建一个自动配置类MapperAutoConfig,并通过@Import引入自定义的Registrar。

@Configuration
@Import(MapperAutoConfigureRegistrar.class)
public class MapperAutoConfig {
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值