@Import是Spring注入Bean的方式之一。
为什么有这个
先看其他的方式:
- @Component及其对应的衍生注解就不用说了,这些只能在当前包下,或者@ComponentScan扫描的路径下面,这种方式在自己项目中方便,但是需要和第三放项目结合的时候就不方便了。
- @Bean这种注入方式一般是用来引入第三方组件的:别的组件有对象类信息,我们new出来注入进去。这种方式要在@Configuration中写方法,如果业务逻辑复杂,或者要注入的东西过多,也不方便。
而我们需要有一些其他的注入方式需求:
- 动态注入bean:bean的注入不是写死在逻辑里面的,是依据某些用户使用条件的。这也是框架所需要的,我们应该依据用户怎么配置,决定我们给容器注入什么bean。
- 在加载某个配置文件之前,先加载其他的配置文件:这个方式有其他的方式解决,但是对应@Configuration的类,采用@Import比较更好些。
- 批量注入bean:某个框架希望在用户配置某项之后,注入很多个bean进去,那么Import可以写代码逻辑批量注入bean。
- 持续补充中...
@Import 一般是Spring和其他框架整合的时候使用的。我们使用@Component及其组合组件的时候,这些组件是可以被我们自己项目扫描到的,但是其他框架中的一些组件我们需要加载进来的时候(它不在我们项目包下) ,这就可以使用@Import将其加载进来。除此以外,默认的@Import注入的东西的加载要先于当前的配置类(除了DeferredImportSelector实现类)。
用法
@Import可以有三种用法
导入普通类
可以导入普通的类,也可以导入一个@Configuration注解的类,那么配置类将优先先加载。
@Import(value = {Bean.class, Configuration.class})
导入ImportSelector接口实现类
主要作用是收集需要导入的配置类,会将selectImports方法返回的id的对象注入到Spring容器中。
SpringBoot的自动化配置和@EnableXXX注解一般都会使用这个,他可以依据参数(从注解中获取的参数值)来决定向容器中注入对应的bean。
@Import(value = {CustomImportSelector.class})
public class CustomImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 返回类的全限定类名,不管该类是不是Spring注解标注bean都会生成bean。
return new String[]{"com.xx.Bean"};
}
}
常用方式:
- 直接在配置类上使用@Import ImportSelector实现类
- 通过EnableXXX注解,在Enable注解上@Import ImportSelector实现类,然后我们再依据Eanble注解中的参数来判断需要加载哪个配置Bean到Spring容器中。
什么时候用?
- 需要自定义@EnableXXX类似功能的场景
- 需要批量的注入Bean的场景
导入ImportBeanDefinitionRegistrar接口实现类
ImportBeanDefinitionRegistrar也是一个接口,这个类只是注册Bean的方式可以更加自由,让我自己来创建BeanDefinition并注册到容器中去。这个适合更加复杂的一些框架整合上,我们可以更加灵活的定制我们需要注入容器的bean元素。
@Import(value = {CustomBeanDefinitionRegister.class})
public class CustomBeanDefinitionRegister implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Bean.class);
registry.registerBeanDefinition("bean", rootBeanDefinition);
}
}