有时我们需要在某个配置类中导入其他一些类,并且导入的类也会被添加到 Spring 容器中。此时,可以使用@Import 注解来完成此功能。
如果你看过它的源代码,会发现导入的类支持三种不同的类型。
然而,我认为最好将普通类和带有@Configuration 注解的配置类分开解释。因此,列出了四种不同的类型:
1. 导入普通类
这种导入方式最简单。导入的类将被实例化为一个 bean 对象。
public class A {
}
@Import(A.class)
@Configuration
public class TestConfiguration {
}
通过@Import 注解导入类 A,Spring 可以自动实例化对象 A。然后,可以在需要的地方通过@Autowired 注解进行注入:
@Autowired
private A a;
是不是很神奇?不需要添加@Bean 注解就可以实例化对象。
2. 导入带有@Configuration 注解的配置类
这种导入方式最复杂,因为@Configuration 注解还支持多种组合注解,例如:
@Import @ImportResource @PropertySource 等
public class A {
}
publicclass B {
}
@Import(B.class)
@Configuration
public class AConfiguration {
@Bean
public A a() {
return new A();
}
}
@Import(AConfiguration.class)
@Configuration
public class TestConfiguration {
}
通过@Import 注解导入一个带有@Configuration 注解的配置类,与该配置类相关的@Import、@ImportResource 和@PropertySource 等注解导入的所有类将一次性全部导入。
3. ImportSelector
这种导入方式需要实现 ImportSelector 接口:
public class AImportSelector implements ImportSelector {
private static final String CLASS_NAME = "com.demo.cache.service.A";
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{CLASS_NAME};
}
}
@Import(AImportSelector.class)
@Configuration
public class TestConfiguration {
}
这种方法的优点是 selectImports 方法返回一个数组,这意味着可以非常方便的导入多个类。
4. ImportBeanDefinitionRegistrar
这种导入方式需要实现 ImportBeanDefinitionRegistrar 接口:
public class AImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(A.class);
registry.registerBeanDefinition("a", rootBeanDefinition);
}
}
@Import(AImportBeanDefinitionRegistrar.class)
@Configuration
public class TestConfiguration {
}