
@Import注解使用详解 原创
@Import注解使用详解
Import注解定义源码
Import
注解源码的定义非常简单,就一个属性 value
,而且是一个 Class
类型的数组。
结合上面的注释,对我们了解Import
有很大的帮助。
- 可以同时导入多个
@Configuration
类 、ImportSelector 和 ImportBeanDefinitionRegistrar
的实现,以及导入普通类(4.2版本开始支持) @Import
的功能与 xml 中的<import/>
标签等效- 在类级别声明或作为元注释
- 如果需要导入XML 或其他非bean 定义资源,请使用
@ImportResource
注解
支持的三种类型
- 实现
ImportSelector
接口的类 - 实现
ImportBeanDefinitionRegistrar
接口的类 - 不是上述两种情况,将类作为配置类处理。
接下来小杰带大家来看看使用过程。
代码测试
@Import导入普通类
- 提供
ImportTest
类,该类没有任何注解标注
- 扫描并使用
@Import
导入ImportTest
类,进行启动
@Import导入配置类
这里说的配置类是被 @Configuration
标注的类。
- 启动结果和导入普通类一致。区别在于 被
@Configuration
标注的类会被 CGLIB 进行代理。
实现 ImportSelector
基本使用
- 创建
ImportSelectorComponent
类,该类会被导入。
- 创建
ImportSelectorTest
类,实现ImportSelector
接口,并重写selectImports
方法,方法返回的是需要导入类的全限定名的数组。
@Import
导入的值修改为ImportSelectorTest.class
,并进行启动
注意被ImportSelector
导入的类的 beanName 是类的全限定名称,实现 ImportSelector 的类不会被注入容器中。
效果达到之后,你会发现这种使用方式有点繁琐,还要写一个实现类。觉得并没有什么用,直接使用 import
直接导入不更优雅吗。的确是的,如果是导入固定的 Bean 定义,这种方式肯定不是最优的。所以它的用途在其他方向,比如需要进行一些逻辑处理之后,进行动态注册时,该方式是非常有用的。在 Spring
、Spring Boot
底层大量使用该方式进行导入Bean定义。
源码定义
ImportSelector
接口的源码也是很简单的。接口中就一个selectImports
方法。方法的参数是AnnotationMetadata
,通过该参数我们可以获得被 @Import
标注的类的各种信息,比如:Class名称,实现的接口名称、父类名称、类上的其他注解信息。
代码示例小杰就不写了,我们看看 Spring
的处理方式。找到ImportSelector
接口的抽象子类 AdviceModeImportSelector
,当我们在启动类上加上 @EnableAsync
或者@EnableCaching
就会进行到这里。
代码意思也不阐述了,打个断点跑一遍就清楚了。
我们来看看接口上的注释,大意如下:
DeferredImportSelector
与 SpringBoot自动装配
有很大的关系,这个到Spring Boot
系列再说。
实现 ImportBeanDefinitionRegistrar
基本使用
- 创建
ImportBeanDefinitionRegistrarComponent
普通类
- 创建
ImportBeanDefinitionRegistrarTest
,实现ImportBeanDefinitionRegistrar
接口,并重写registerBeanDefinitions
方法
@Import
导入的值修改为ImportBeanDefinitionRegistrarTest.class
,并进行启动
注意被ImportBeanDefinitionRegistrar
注册的类的 beanName 是可以自定义的,实现 ImportBeanDefinitionRegistrar
的类不会被注入容器中。
源码释义跟 ImportSelector
差不多,就不在阐述。
自定义注解
接下来小杰将使用 ImportBeanDefinitionRegistrar
实现,添加了我们自定义的@Cxyxj
注解的类会被自动加入到Spring容器中。
- 自定义注解 Cxyxj
- 修改
ImportBeanDefinitionRegistrarTest
类的代码,修改如下:
- 启动类
该效果使用 ImportSelector
也是可以实现的。
