前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot源码学习(十四)- 动态bean注册

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

作者头像
写一点笔记
发布2020-12-31 10:17:47
5960
发布2020-12-31 10:17:47
举报
文章被收录于专栏:程序员备忘录程序员备忘录

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

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

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

代码语言:javascript
复制
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
public @interface  TianMapper {
}

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

代码语言:javascript
复制
@TianMapper
@Data
public class TianConfig {

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

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

代码语言:javascript
复制
@Data
public class TianClassPathMapperScanner extends ClassPathBeanDefinitionScanner {

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

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

代码语言:javascript
复制
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中。

代码语言:javascript
复制
@Import(TianImportBeanDefinitionRegistrar.class)

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

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

二,实现的原理

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

在invokeBeanFactoryPostProcessors(beanFactory);方法中,

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

代码语言:javascript
复制
   private void loadBeanDefinitionsFromRegistrars(Mapregistrars) {
          registrars.forEach((registrar, metadata) ->
                        registrar.registerBeanDefinitions(metadata, this.registry));
   }

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员备忘录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档