前言
平常在使用SpringBoot
的过程中,经常会使用到@EnableXXX
的注解,而随之一起的还有一个@Import
注解,这次就专门来看@Import
的源码
正文
先摘抄一部分它的英文注释吧:
1 |
|
大概意思就是:
- 可以导入一个类或多个类至容器中,和xml中的import标签功能一样
- 可导入普通类,Configuration类,ImportSelector或ImportBeanDefinitionRegistrar接口的实现类
- 导入配置文件,该配置文件可被其他的bean注入,也可以在配置中注入其他的bean。
例子
- 新建一个
springboot
项目 - 在启动类上层建立同层级的包。例如,启动类
test.java
在a.b.c.d
下面,那么在c
包下建立e
包,e
和d
处于同一级目录。
为什么要有第二点,因为springboot
会扫描启动类同级目录下的文件,如果在同一级目录,直接使用@Componment就行了。所以个人觉得@Import
就是导入与项目不是同一级目录的类。
导入普通类
在e包下新建两个类,TestImportA和TestImportB:
1 |
|
然后在启动类上面添加:
1 |
|
这样,不会被扫描到的TestImportA.class, TestImportB.class就可以通过@Import注解扫描到,并放进容器了。
导入配置类
在e包下新建配置类TestImportConfig
1 |
|
然后在启动类上面添加:
1 |
|
效果和第一种是一样的。
导入ImportSelector的实现类
- 新建一个注解类TestImport
1 |
|
说一下为什么要新建一个注解类。
ImportSelector的接口String[] selectImports(AnnotationMetadata importingClassMetadata)
,该接口接收了一个AnnotationMetadata,
这个类里面就包含了@Import注解所在的地方(类,接口,枚举)的注解信息,这样我们就可以在启动配置的时候获取一些需要的信息了。最典型的就是@EnableXXX注解,
在@EnableXXX中使用@Import导入ImportSelector实现类,这样就可以获取@EnableXXX注解的一些信息了。
- 新建一个ImportSelectorImpl来实现ImportSelector接口
1 |
|
- 在启动类上改用@TestImport注解
1 |
|
导入ImportBeanDefinitionRegistrar的实现类
这个用法和ImportSelector的用法是一样的,这里就不全展示了,直接在TestImport注解上换成@Import(ImportBeanDefinitionRegistrarImpl.class)就行了。
- 新建ImportBeanDefinitionRegistrar实现类
1 |
|
最后
还记得最近的面试中,被问到了如何向spring容器中注册bean,当时我的回答是:
- @Component,@Service,@Controller,@Repository这四个注解,后三个底层都是用的@Component。
- @Configuration,在配置类中使用@Bean注册
- BeanFactoryAware, ApplicationContextAware,实现这两个接口,然后手动向容器中注册。
这次就可以另外加上一个@Import,ImportBeanDefinitionRegistrar以及ImportSelector了。