一、@Import
@Import:可以说是向容器中注册组件的第三种方式,快速的给容器中导入一个组件
1.导入配置类
如果将所有的配置都放到一个配置类当中的话,那么这个唯一的配置类就会显得相当的臃肿。这个时候我们可以将不同的配置放在不同的配置类当中,然后在某个配置类当中使用@Import注解导入其他的配置类。这个作用可以用于依赖第三方包中bean的配置和加载。
配置类1:
/**
*此处没有使用@Configuration注解
*/
public class ImportConfig {
@Bean
public Student student(){
return new Student();
}
@Bean
public Teacher teacher(){
return new Teacher();
}
}
配置类2:
@Configuration
@ComponentScan(value = "com.baiding")
// 此处使用@Import注解导入ImportConfig配置类
@Import(ImportConfig.class)
public class BeanConfig {
/**
* 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
* @return
*/
@Bean(name = "wangwu")
public Person person(){
return new Person("wangwu",22);
}
}
测试实例:
@Test
void test04(){
ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
String[] names = ac.getBeanDefinitionNames();
for(String name :names){
System.out.println(name);
}
}
结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
com.baiding.config.ImportConfig
student
teacher
wangwu
从结果中可以看出:IOC容器中已经有了student和teacher这两个组件,证明Import导入生效。另外容器中还有一个id为com.baiding.config.ImportConfig的组件,这是因为使用@Import导入某个配置类时,容器中就会自动注册这个组件,id默认是全类名。
2.导入普通Java类
在Spring4.2之后,@Import注解支持导入普通的java类,并将其声明成一个bean。
配置类:
@Configuration
@ComponentScan(value = "com.baiding")
// 此处导入两个普通Java类
@Import({Student.class, Teacher.class})
public class BeanConfig {
/**
* 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
* @return
*/
@Bean(name = "wangwu")
public Person person(){
return new Person("wangwu",22);
}
}
测试实例:
@Test
void test05(){
ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
String[] names = ac.getBeanDefinitionNames();
for(String name :names){
System.out.println(name);
}
Student student =ac.getBean(Student.class);
student.doSomeThing();
Teacher teacher = ac.getBean(Teacher.class);
teacher.doSomeThing();
}
结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
com.baiding.model.Student
com.baiding.model.Teacher
wangwu
I'm student...
I'm teacher...
从结果可以看出:使用@Import注解导入普通的Java类,依然可以将之成功注册到IOC容器中去,并且组件的id是普通Java类的全类名。
二、ImportSelector
ImportSelector是一个接口,实现这个接口自定义返回需要导入的组件的全类名就可以了。spring boot会大量用到这种方式。
配置类:BeanImportSelector
public class BeanImportSelector implements ImportSelector {
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.baiding.model.Doctor"};
}
}
配置类:BeanConfig
@Configuration
@ComponentScan(value = "com.baiding")
// 此处导入实现了ImportSelector接口的实现类
@Import({Student.class, Teacher.class, BeanImportSelector.class})
public class BeanConfig {
/**
* 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
* @return
*/
@Bean(name = "wangwu")
public Person person(){
return new Person("wangwu",22);
}
}
测试实例:
@Test
void test05(){
ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
String[] names = ac.getBeanDefinitionNames();
for(String name :names){
System.out.println(name);
}
Student student =ac.getBean(Student.class);
student.doSomeThing();
Teacher teacher = ac.getBean(Teacher.class);
teacher.doSomeThing();
Doctor doctor =ac.getBean(Doctor.class);
doctor.doSomeThing();
}
结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
beanConfig
com.baiding.model.Student
com.baiding.model.Teacher
com.baiding.model.Doctor
wangwu
I'm student...
I'm teacher...
I'm doctor...
可以看出Doctor类成功注册到IOC容器中去了。组件的id就是ImportSelector接口实现类中方法返回的全类名。
三、ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar是一个接口,实现这个接口,可以手动注册bean到容器中去。
接口实现类:
public class SimpleImportBeanDefinitionRegistry implements ImportBeanDefinitionRegistrar {
/**
*
* @param annotationMetadata
* 当前类的注解信息
* @param beanDefinitionRegistry
* BeanDefinition注册类
*/
public void registerBeanDefinitions(AnnotationMetadata am, BeanDefinitionRegistry br) {
boolean flag = br.containsBeanDefinition("com.baiding.model.Student");
boolean flag2 = br.containsBeanDefinition("wangwu");
if(flag && flag2){
RootBeanDefinition beanDefinition= new RootBeanDefinition(Person.class);
br.registerBeanDefinition("zhangsan",beanDefinition);
}
}
}
配置类:
@Configuration
@ComponentScan(value = "com.baiding")
@Import({Student.class, Teacher.class, BeanImportSelector.class,
SimpleImportBeanDefinitionRegistry.class})
public class BeanConfig {
/**
* 给容器中注册一个bean 类型为返回值的类型 id默认为方法名或者直接用属性name配置id
* @return
*/
@Bean(name = "wangwu")
public Person person(){
return new Person("wangwu",22);
}
}
测试实例:
@Test
void test06(){
ApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
String[] names = ac.getBeanNamesForType(Person.class);
for(String name :names){
System.out.println(name);
}
}
结果:
wangwu
zhangsan