SpringBoot源码学习(十四)- 动态bean注册

在看源码的时候,我们发现了一个接口ImportBeanDefinitionRegistrar,当时只是简单的了解了一下spring的大概,没有做复习。在我们开始学习mybatis源码的时候,发现这个接口成为我们必要学习的东西。那么这个接口是做什么的,还有就是这个接口的原理是什么。怀着疑问,让我们学习一下吧!

首先我们还是不去直接看原理,我们还是先根据网上资料实践一下这个接口的功能。根据资料,该接口的主要作用就是用来动态的注入bean到spring ioc中。但是问题是什么是动态,或者怎么样的操作才算是动态。难道以前都不算动态吗。作者对这里的动态的理解是可以用户自定义的决定注入哪些类。这里的自定义就是规则。根据作者的实践,认为就是注入作者自定义的注解的bean到ioc容器中。那么如何实现一个自定义的动态注入器。这里我们就实践一下。

       1.自定义定义注解(相当于打个标志,让spring扫描的时候进行识别)

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

2.定义要注入的类(该类被自定义注解修饰

@TianMapper
@Data
public class TianConfig {


    public String toString(){
        return this.getClass()+"TianConfig";
    }
})

3.自定义扫描器(自定义扫描的包和限制被扫描的类的标志等)

@Data
public class TianClassPathMapperScanner extends ClassPathBeanDefinitionScanner {


    private Class annotationClass;
    
    public TianClassPathMapperScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }
}

4.实现ImportBeanDefinitionRegistrar接口,在spring启动时候扫描自定义注解的类

public class TianImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, BeanFactoryAware {


    private ResourceLoader resourceLoader;
    private BeanFactory beanFactory;


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


    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        TianClassPathMapperScanner tianClassPathMapperScanner=new TianClassPathMapperScanner(registry);
        //设置基本的注解
        tianClassPathMapperScanner.setAnnotationClass(TianMapper.class);
       //设置运行被扫描的注解
        tianClassPathMapperScanner.addIncludeFilter(new AnnotationTypeFilter(TianMapper.class));
         //设置需要进行扫描的包
        tianClassPathMapperScanner.scan("com.scaffold.simple.admin.springtest");
    }


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

5.将需要被spring启动执行的接口加入到ioc中。

@Import(TianImportBeanDefinitionRegistrar.class)

运行源代码,发现我们的TianConfig已经注入进去了。

通过上述的学习,我们就大概知道该接口就是对spring类扫描规范的一种扩展,可以让我们开发人员自定义注解然后交由ioc容器进行管理。其实这种用法在一些第三方包中应用的非常广泛。比如开始的时候说的mybatis。

二,实现的原理

作者通过代码跟踪,最后发现最终调用的访问如下:

在invokeBeanFactoryPostProcessors(beanFactory);方法中,

最终的调用实现是for循环实现。

   private void loadBeanDefinitionsFromRegistrars(Mapregistrars) {
          registrars.forEach((registrar, metadata) ->
                        registrar.registerBeanDefinitions(metadata, this.registry));
   }

总结:spring在invokeBeanFactoryPostProcessors方法对类进行类级别注解解析扫描的时候,顺便就将ImportBeanDefinitionRegistrar接口的实现类标记出来。并进行全部解析然后转化成初级的beandefine,并在最后的onfresh过程中真正的实例化。

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值