掌握@Import的用法是我们阅读spring源码的必要条件,以下做一个总结
- 直接填class数组方式
- ImportSelector方式
- ImportBeanDefinitionRegistrar方式
1)直接填class数组的方式
/**
* description:
* 测试@import的用法,同时引入两个bean
* 直接填class数组方式
* author:dingyawu
* date:created in 23:37 2020/12/4
* history:
*/
@Configuration
@Import({Person.class, Employee.class})
public class PersonConfig8 {
}
测试demo
@Test
public void testImport() {
ApplicationContext ac = new AnnotationConfigApplicationContext(PersonConfig8.class);
String[] names = ac.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
personConfig8
com.roy.beans.Person
com.roy.beans.Employee
- ImportSelector的方式 ImportSelector的实现类
public class MyImportSelector implements ImportSelector {
/**
* 返回值为需要导入到容器中的bean的全类名数组
* AnnotationMetadata:当前标注@Import注解的类的所有注解信息
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{Person.class.getName(), Employee.class.getName()};
}
}
配置类
@Configuration
@Import({User.class, MyImportSelector.class})
public class PersonConfig9 {
}
测试demo 证明容器中是有Person和Employee两个bean的
/** 测试MyImportSelectord的用法,可以一次性注入好多bean */
@Test
public void testMyImportSelector() {
ApplicationContext ac = new AnnotationConfigApplicationContext(PersonConfig9.class);
String[] names = ac.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
3) ImportBeanDefinitionRegistrar方式
ImportBeanDefinitionRegistrar的实现类,定义有具体的要注入的bean,写有注入bean的条件
/**
* description:
* author:dingyawu
* date:created in 22:19 2020/12/5
* history:
*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* AnnotationMetadata: 当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
* 通过调用BeanDefinitionRegistry接口的registerBeanDefinition()方法,可以将所有需要添加到容器中的bean注入到容器中。
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
boolean user = registry.containsBeanDefinition(User.class.getName());
boolean person = registry.containsBeanDefinition(Person.class.getName());
if (user && person){
BeanDefinition beanDefinition = new RootBeanDefinition(StudentBean.class);
registry.registerBeanDefinition("studentBean", beanDefinition);
}
}
}
配置类:
/**
* description:
* 测试MyImportBeanDefinitionRegistrar,注入bean的时候用这种方式带条件注入
* 个人理解也是mybatis等产品侵入spring的一种方式,是spring容器接入第三方产品的方式
* author:dingyawu
* date:created in 23:37 2020/12/4
* history:
*/
@Configuration
@Import({User.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class PersonConfig10 {
}
测试demo:
/** 测试@import中MyImportBeanDefinitionRegistrar的用法 */
@Test
public void testMyImportBeanDefinitionRegistrar() {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(PersonConfig10.class);
String[] names = ac.getBeanDefinitionNames();
Arrays.stream(names).forEach(System.out::println);
}
一般我们都是通过在@Import注解中使用ImportSelector接口或者ImportBeanDefinitionRegistrar来导入bean
ImportSelector接口是至spring中导入外部配置的核心接口,主要用来收集需要导入的配置类 通常我们会模拟实现@EnbaleXXX功能,在@EnbaleXXX这个注解上加入@Import注解