导读:@Import 和 @ImportResource或许很多人都用过,并且都还没有用错。但是若真把他俩拿过来一起的时候,却有点傻傻分不清楚了。总结本篇文章希望对从事相关工作的同学能够有所帮助或者启发      

在平时看源码或者很多配置类上面都会出现@Import注解,功能就是和Spring XML 里面 的 一样. @Import注解是用来导入配置类或者一些需要前置加载的类.

一、背景


@Import和@ImportResource是的,他俩都有导入的含义,但是使用起来还是有很大的区别的,因此本文主要针对于他俩的区别,顺便从一定的原理的角度做一个解释,希望大家以后能区分开来。

在讲解之前,可以记住一个通用的的结论:

  • @Import主要用于导入类对象与另一个类对象的依赖;

  • @ImportResource主要用于在SpringBoot中显示指定从自定义的配置文件中生成bean而不是通过@Bean注解生成Bean

本文主要详解@Import 结合一些案例场景分析,后续有时间针对@Import 和 @ImportResource 进行对比讲解。总结本篇文章希望对从事相关工作的同学能够有所帮助或者启发。

二、@Import 注解解读


▐ 导读配置的三种类型

@Import支持 三种方式

  • 带有@Configuration的配置类(4.2 版本之前只可以导入配置类,4.2版本之后 也可以导入普通类)

  • ImportSelector 的实现

  • ImportBeanDefinitionRegistrar 的实现

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

 /**
  * {@link Configuration @Configuration}, {@link ImportSelector},
  * {@link ImportBeanDefinitionRegistrar},&nbs***bsp;regular component classes to import.
  */
 Class<?>[] value();

}

二、@Import 案例实践


▐ 导入普通类

定义普通类

public class ABeanDefinition {

    public String printName() {
        return "类名 :" + Thread.currentThread().getStackTrace()[1].getClassName();
    }
}

新建一个ImportConfig,在类上面加上@Configuration,加上@Configuration是为了能让Spring 扫描到这个类,并且直接通过@Import引入ABeanDefinition类

@Import({ABeanDefinition.class})
@Configuration
public class ImportConfiguration {
}

JUnit4测试结果

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EngineSupportApplication.class)
public class ImportAnnotationInstance {

    @Autowired(required = false)
    ABeanDefinition aBeanDefinition;

    @Autowired(required = false)
    BBeanDefinition bBeanDefinition;

    @Autowired(required = false)
    CBeanDefinition cBeanDefinition;

    @Autowired(required = false)
    DBeanDefinition dBeanDefinition;

    @Test
    public void invokeADefaultMethod() {
        System.out.println("A====================================");
        System.out.println(aBeanDefinition.printName());
    }

    @Test
    public void invokeBDefaultMethod() {
        System.out.println("B====================================");
        System.out.println(bBeanDefinition.printName());
    }

    @Test
    public void invokeCDefaultMethod() {
        System.out.println("C====================================");
        System.out.println(cBeanDefinition.printName());
    }

    @Test
    public void invokeDDefaultMethod() {
        System.out.println("D====================================");
        System.out.println(dBeanDefinition.printName());
    }
}

▐ 导入带有@Configuration的配置类

定义带有@Configuration 的配置类

@Configuration
public class BBeanDefinition {

    public String printName() {
        return "类名 :" + Thread.currentThread().getStackTrace()[1].getClassName();
    }
}

通过@Import引入BBeanDefinition类(4.2 版本之前只可以导入配置类,4.2版本之后 也可以导入普通类),高版本可省略此步骤。

@Import({BBeanDefinition.class})
public class ImportConfiguration {
}

JUnit4测试结果

▐ 通过ImportSelector 方式导入的类

定义测试类

public class CBeanDefinition {

    public String printName() {
        return "类名 :" + Thread.currentThread().getStackTrace()[1].getClassName();
    }
}

新建SelfImportSelector.class 实现ImportSelector 接口,注入CBeanDefinition

public class SelfImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.alibaba.spring.annotations.CBeanDefinition"};
    }
}

ImportConfiguration上面引入SelfImportSelector.class

@Import({SelfImportSelector.class})
@Configuration
public class ImportConfiguration {
    
}

JUnit4测试结果

▐ 通过 ImportBeanDefinitionRegistrar 方式导入的类

定义测试类

public class DBeanDefinition {

    public String printName() {
        return "类名 :" + Thread.currentThread().getStackTrace()[1].getClassName();
    }
}

新建SelfImportBeanDefinitionRegistrar.class,实现接口ImportBeanDefinitionRegistrar,注入DBeanDefinition.class

public class SelfImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition root = new RootBeanDefinition(DBeanDefinition.class);
        registry.registerBeanDefinition("dBeanDefinition", root);
    }
}

ImportConfiguration上面引入SelfImportBeanDefinitionRegistrar.class

@Import({DBeanDefinition.class})
@Configuration
public class ImportConfiguration {
}

JUnit4测试结果

三、总结


@Import 的使用如果基于内部项目来使用-用处不大,在高版本中完全可以使用@Configuration替换。但是当你项目里需要引用一些第三方的依赖,@Configuration注解的类包名都跟你不一样,包自动扫描就不会去自动加载。这个时候就需要@import了。

原文地址:Spring 中 @Import 注解三种使用场景解读

如果你觉的本文对你有帮助,麻烦点赞关注支持一下