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

}

 


  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM