根据注解 自动注册bean ImportBeanDefinitionRegistrar

简介
ImportBeanDefinitionRegistrar类只能通过其他类@Import的方式来加载,通常是启动类或配置类。
使用@Import,如果括号中的类是ImportBeanDefinitionRegistrar的实现类,则会调用接口方法,将其中要注册的类注册成bean。
实现该接口的类拥有注册bean的能力。
手动把一个类注册成bean
首先写一个类,最终要把它注册为bean。

  public class HelloService {

  }


自定义ImportBeanDefinitionRegistrar实现类手动注册bean。 

 public class HelloImportBeanDefinitionRegistrar 
          implements ImportBeanDefinitionRegistrar {

      /**
       * @Description AnnotationMetadata:当前类的注解信息;
       * BeanDefinitionRegistry:注册类,其registerBeanDefinition()可以注册bean
       **/
      @Override
      public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                          BeanDefinitionRegistry registry) {
  
          //扫描注解
          Map<String, Object> annotationAttributes = importingClassMetadata
              .getAnnotationAttributes(ComponentScan.class.getName());
          String[] basePackages = (String[]) annotationAttributes.get("basePackages");
  
          //扫描类
          ClassPathBeanDefinitionScanner scanner =
                  new ClassPathBeanDefinitionScanner(registry, false);
          TypeFilter helloServiceFilter = new AssignableTypeFilter(HelloService.class);
          
          scanner.addIncludeFilter(helloServiceFilter);
          scanner.scan(basePackages);
      }
  
  }


最后定义一个配置类发现一下上面的ImportBeanDefinitionRegistrar实现类。

  @Configuration
  @ComponentScan("com.haien.import2.domain")
  @Import(HelloImportBeanDefinitionRegistrar.class)
  public class HelloConfiguration {
  
  }



测试:

  @RunWith(SpringRunner.class)
  @SpringBootTest
  @ContextConfiguration(classes = {HelloConfiguration.class}) //表示只需要这一个文件
  public class DemoApplicationTest2 {
  
      @Resource
      HelloService helloService;
  
      /**
       * @Description 扫描到helloService
       **/
      @Test
      public void contextLoads(){
          System.out.println(helloService.getClass());
      }
  }


自己写一个注解实现@Component的功能
目标:自己写一个注解@Mapper,配合其他类,实现被注解类可以被注册成bean的功能。

@Mapper:

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


注释于类上:

  @Mapper
  public class CountryMapper {
  }


实现ImportBeanDefinitionRegistrar接口,重写registerBeanDefinitions方法,手动注册bean;同时实现一些Aware接口,以便获取Spring的一些数据。

public class MapperAutoConfiguredMyBatisRegistrar implements
          ImportBeanDefinitionRegistrar,ResourceLoaderAware,BeanFactoryAware {
      
      private ResourceLoader resourceLoader;
      private BeanFactory beanFactory;
  
      /**
       * @Description 注册bean,但我们并不知道需要注册哪些bean,所以需要借助
       * ClassPathBeanDefinitionScanner扫描器,扫描我们需要注册的bean
       **/
      @Override
      public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
                                          BeanDefinitionRegistry registry) {
          
          MyClasssPathBeanDefinitionScanner scanner=
                  new MyClasssPathBeanDefinitionScanner(registry,false);
          scanner.setResourceLoader(resourceLoader);
          scanner.registerFilters();
          scanner.doScan("com.haien.import1.domain");
      }
  
      @Override
      public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
          this.beanFactory=beanFactory;
      }
  
      @Override
      public void setResourceLoader(ResourceLoader resourceLoader) {
          this.resourceLoader=resourceLoader;
      }
  
  }


以上我们还借助了扫描器ClassPathBeanDefinitionScanner,通过它来获取我们需要注册的bean。

  public class MyClasssPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner {

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


  
   

  /**
       * @Description 注册条件过滤器,将@Mapper注解加入允许扫描的过滤器中,
       * 如果加入排除扫描的过滤器集合excludeFilter中,则不会扫描
       **/
      protected void registerFilters(){
          addIncludeFilter(new AnnotationTypeFilter(Mapper.class));
      }
  
      @Override
      protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
          return super.doScan(basePackages);
      }
  }



测试:

 @RunWith(SpringRunner.class)
  @SpringBootTest(classes = MapperAutoConfig.class)
  //只将MapperAutoConfig类纳入测试环境的Spring容器中,
  //或@ContextConfiguration(classes = {MapperAutoConfig.class})
  public class DemoApplicationTest {
  
      @Resource
      CountryMapper countryMapper;
  
      /**
       * @Description 扫描不到CountryMapper
       **/
      @Test
      public void contextLoads(){
          System.out.println(countryMapper.getClass());
      }
  }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值