阅读 214

Spring之@Import

@Import是Spring注入Bean的方式之一。

为什么有这个

先看其他的方式:

  • @Component及其对应的衍生注解就不用说了,这些只能在当前包下,或者@ComponentScan扫描的路径下面,这种方式在自己项目中方便,但是需要和第三放项目结合的时候就不方便了。
  • @Bean这种注入方式一般是用来引入第三方组件的:别的组件有对象类信息,我们new出来注入进去。这种方式要在@Configuration中写方法,如果业务逻辑复杂,或者要注入的东西过多,也不方便。

而我们需要有一些其他的注入方式需求:

  1. 动态注入bean:bean的注入不是写死在逻辑里面的,是依据某些用户使用条件的。这也是框架所需要的,我们应该依据用户怎么配置,决定我们给容器注入什么bean。
  2. 在加载某个配置文件之前,先加载其他的配置文件:这个方式有其他的方式解决,但是对应@Configuration的类,采用@Import比较更好些。
  3. 批量注入bean:某个框架希望在用户配置某项之后,注入很多个bean进去,那么Import可以写代码逻辑批量注入bean。
  4. 持续补充中...

@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"};
    }
}
复制代码

常用方式:

  1. 直接在配置类上使用@Import ImportSelector实现类
  2. 通过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);
    }
}
复制代码
文章分类
后端
文章标签