Java SpringBoot @Import
@Import注解算是SpringBoot自动配置原理中一个很重要的注解

认识@Import注解

👀先看一下源码

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface Import {
  5. /**
  6. * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
  7. * or regular component classes to import.
  8. */
  9. Class<?>[] value();
  10. }

@Import表示要导入的一个或多个@Configuration
看注释value通常是一个普通的组件,ConfigurationImportSelectorImportBeanDefinitionRegistrar

搭建项目结构用于测试

1. 先创建一个maven工程

2. 加入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.projectlombok</groupId>
  4. <artifactId>lombok</artifactId>
  5. <version>1.18.18</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework</groupId>
  9. <artifactId>spring-context</artifactId>
  10. <version>4.3.24.RELEASE</version>
  11. </dependency>
  12. </dependencies>

3. 编写测试代码

Tom.java

  1. @Data
  2. public class Tom {
  3. private String color;
  4. private Integer age;
  5. }

AppConfig.java

  1. @Configuration
  2. public class AppConfig {
  3. }

App.java

  1. public class App {
  2. public static void main(String[] args) {
  3. // 创建容器
  4. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  5. // 获取bean
  6. Tom tom = context.getBean(Tom.class);
  7. System.out.println(tom);
  8. }
  9. }

@Import用法

第一种普通组件

@Import({要导入的容器中的组件})
CustomConfiguration.java

  1. @Configuration
  2. public class CustomConfiguration {
  3. @Bean
  4. public Tom tom() {
  5. Tom tom = new Tom();
  6. tom.setAge(11);
  7. tom.setColor("红色");
  8. return tom;
  9. }
  10. }

将AppConfig.java加上@Import({ CustomConfiguration.class })

  1. @Import({ CustomConfiguration.class })
  2. @Configuration
  3. public class AppConfig {
  4. }

这个时候运行App已经可以获取到Tom

第二种ImportSelector

  1. CustomSelector.java
  2. public class CustomSelector implements ImportSelector {
  3. @Override
  4. public String[] selectImports(AnnotationMetadata importingClassMetadata) {
  5. return new String[] { "com.moli.pojo.Tom" };
  6. }
  7. }

将AppConfig.java加上@Import({ CustomRegistrar.class })

  1. @Import({ CustomRegistrar.class })
  2. @Configuration
  3. public class AppConfig {
  4. }

这个时候运行App已经可以获取到Tom

第三种ImportBeanDefinitionRegistrar

CustomRegistrar.java

  1. public class CustomRegistrar implements ImportBeanDefinitionRegistrar {
  2. @Override
  3. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  4. BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(Tom.class);
  5. builder.setScope(BeanDefinition.SCOPE_SINGLETON);
  6. builder.addPropertyValue("color", "灰色");
  7. builder.addPropertyValue("age", "12");
  8. registry.registerBeanDefinition("tom", builder.getBeanDefinition());
  9. }
  10. }

将AppConfig.java加上@Import({ CustomSelector.class })

  1. @Import({ CustomSelector.class })
  2. @Configuration
  3. public class AppConfig {
  4. }

这个时候运行App已经可以获取到Tom

最佳搭档 - @Import通用形式

在开源软件中大部分@Import中是伴随着一个@EnableXXX使用的

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import({ CustomRegistrar.class })
  5. public @interface EnableTom {
  6. }

将AppConfig.java加上@EnableTom

  1. @EnableTom
  2. @Configuration
  3. public class AppConfig {
  4. }

其实SpringBoot的自动配置就是@Import的一个应用

  1. @SuppressWarnings("deprecation")
  2. @Target(ElementType.TYPE)
  3. @Retention(RetentionPolicy.RUNTIME)
  4. @Documented
  5. @Inherited
  6. @AutoConfigurationPackage
  7. @Import(EnableAutoConfigurationImportSelector.class)
  8. public @interface EnableAutoConfiguration {
  9. ...
  10. }

总结

直白一点使用@Import注解可以快速把实例加入Spring的IOC容器中
其实这三种用法也算是一种用法,就是导入一个类到容器,容器根据类的注解类型等信息对不同类进行不同处理;
方法一:导入一个Configuration组件,组件创建了一个Tom类的Bean;
方法二:CustomSelector返回的类的全限定类名,实际上要导入到容器中的组件全类名;
方法三:ImportBeanDefinitionRegistrar类似于第二种ImportSelector用法,只不过这种用法能自定义化注册,往容器内注入一个BeanDefinition,然后BeanDeiniton在容器内转为一个实例bean。