看下注解定义:
* Indicates one or more {@link Configuration @Configuration} classes to import.
*
* <p>Provides functionality equivalent to the {@code <import/>} element in Spring XML.
* Only supported for classes annotated with {@code @Configuration} or declaring at least
* one {@link Bean @Bean} method, as well as {@link ImportSelector} and
* {@link ImportBeanDefinitionRegistrar} implementations.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
/**
* The @{@link Configuration}, {@link ImportSelector} and/or
* {@link ImportBeanDefinitionRegistrar} classes to import.
*/
Class<?>[] value();
}
注解的第一行写的很明白,@Import表明需要引入多个@Configuration注解配置。这就是@Import的用处。
使用条件,指的是Import的属性,即引入的class:必须被@Configuration标注或者至少有一个@Bean注解或者实现了ImportSelector/ImportBeanDefinitionRegistar接口。
我们可能在什么情况下使用这个注解?
自动注册一堆bean。我们可以按业务或者模块划分很多bean,就拿spring来说,基于注解的容器需要一堆的processor,springmvc业务要一堆requestmapping的bean,那么我们可以为每一个模块或者类别搞一个java的config类或者ImportSelector/ImportBeanDefinitionRegistar接口的实现,在需要的时候,在我们的java配置类上使用@Import导入即可。
springmvc的@EnableWebMvc就是一个很好的例子:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
如果要 启用springmvc,那么就要引入相关的bean,我们直接在应用的java配置类上使用@EnableWebMvc即可,相关的bean定义在DelegatingWebMvcConfiguration的父类中通过@Bean的方式定义了。
下面具体看下@Import的使用。
@Bean方式引入:
beans:
public class Player2 {
private CD cd;
public void play(){
cd.sound();
}
public void setCD(CD cd){
this.cd = cd;
}
}
public class CD2 implements CD {
public void sound() {
System.out.println("bababa");
}
}
定义几个@Bean的java配置类:
public class Bean1 {
@Bean(name = "cd2")
public CD2 getCD2(){
return new CD2();
}
}
public class Bean2 {
@Bean(name = "player2")
public Player2 getPlayer2(CD cd){
Player2 player2 = new Player2();
player2.setCD(cd);
return player2;
}
}
定义配置类:
@Configuration
@Import({Bean1.class, Bean2.class})
public class JavaConfig {
}
使用:
public class Main {
public static void main(String args[]) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
Player2 player2 = (Player2) applicationContext.getBean("player2");
player2.play();
}
}
ImportSelector:
public class TestSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
System.out.println(importingClassMetadata.getAnnotationTypes());
return new String[]{Bean1.class.getName(), Bean2.class.getName()};
}
}
这个方法返回需要引入的配置类的类名。入参AnnotationMetadata是被该注解标注的类的注解信息,可以拿到其他标注注解。
这个也是ImportSelector的牛逼之处吧,虽然这个例子并没有体现,与之前的方法一致。但是如果我想拿到其他注解做一些特殊处理,或者对配置类做一些处理,ImportSelector是可以支持的。
具体可以参考下这个例子:https://blog.csdn.net/elim168/article/details/88131614
ImportBeanDefinitionRegistrar:
public class TestRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(CD2.class);
registry.registerBeanDefinition("cd2", builder.getBeanDefinition());
BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.rootBeanDefinition(Player2.class);
registry.registerBeanDefinition("player2", builder1.getBeanDefinition());
}
}
另外需要在Player2类的cd属性上加上@Autowired,因为没有@Bean注解做装配了。