
在看源码的时候,我们发现了一个接口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过程中真正的实例化。

转载:https://blog.csdn.net/tianjingle_blog/article/details/111466045