ImportBeanDefinitionRegistrar接口

ImportBeanDefinitionRegistrar

  spring官方就是用这种方式,实现@Component@Service等注解的动态注入机制。定义一个ImportBeanDefinitionRegistrar的实现类,然后在有@Configuration注解的配置类上使用@Import导入

  需要实现类似@Componet的功能,添加了@Mapper注解的类会被自动加入到spring容器中。

  创建一个@Mapper注解,再新建一个CountryMapper类,使用该Mapper注解

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

@Mapper
public class CountryMapper {
}

  创建MapperAutoConfiguredMyBatisRegistrar实现ImportBeanDefinitionRegistrar,同时可以继承一些Aware接口,获得spring的一些数据

BeanFactoryAware
ResourceLoaderAware
EnvironmentAware

  使用@Import将MapperAutoConfiguredMyBatisRegistrar导入容器

public class MapperAutoConfiguredMyBatisRegistrar
        implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanFactoryAware
{

    private ResourceLoader resourceLoader;

    private BeanFactory beanFactory;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        
    }

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

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}

  实现registerBeanDefinitions方法。但是有一个问题,我们并不知道需要register哪些bean。这里我们还需要借助一个类ClassPathBeanDefinitionScanner,也就是扫描器,通过扫描器获取我们需要注册的bean。先简单看一下spring源码中的的定义

  需要继承ClassPathBeanDefinitionScanner,扫描使用@Mapper的注解的类,ClassPathBeanDefinitionScanner又继承ClassPathScanningCandidateComponentProvider类,ClassPathScanningCandidateComponentProvider中有两个TypeFilter集合,includeFilters、excludeFilters。满足任意includeFilters会被加载,同样的满足任意excludeFilters不会被加载
@Slf4j
public class MyClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner{

    public MyClassPathBeanDefinitionScanner(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);
    }
}

  registerFilters()方法,然后在我们的ImportBeanDefinitionRegistrar实现类中调用

 @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        MyClassPathBeanDefinitionScanner scanner = new MyClassPathBeanDefinitionScanner(registry, false);
        scanner.setResourceLoader(resourceLoader);
        scanner.registerFilters();
        scanner.doScan("com.smart.school.domain");
    }

  测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class SrcDemoApplicationTests {

    @Resource
    private CountryMapper countryMapper;

    @Test
    public void contextLoads() {
        System.out.println(countryMapper.getClass());
    }

}

 


  
posted on 2020-06-13 21:42  溪水静幽  阅读(2752)  评论(0编辑  收藏  举报