Spring Framework 组件注册 之 @Import-让学习成就卓越
source link: https://blog.51cto.com/8950379/2416136
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Spring Framework 组件注册 之 @Import
写在前面
向spring中注册组件或者叫javaBean是使用spring的功能的前提条件。而且spring也提供了很多种方式,让我们可以将普通的javaBean注册到spring容器中,比如前一篇文章Spring Framework 组件注册 之 @Component中写的利用
@Component
注解将普通的javaBean注册到容器中,本文说的@Import
注解也是spring Framework提供的将普通javaBean注册到容器中,以及后续文章会说的@Configuration
,FactoryBean
等方式。
@Import 注册普通Bean
使用@Import
注册一个普通Bean,只需要在@Import
注解中指定待注册Bean的class即可
/**
* 使用Import注解,注册一个普通的Bean
*/
@Data
public class TestImport {
private String id = "@Import";
}
在spring启动引导类中,添加@Import
注解
/**
* spring 容器启动引导类
*/
@Import(TestImport.class)
public class TestImportBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TestImportBootstrap.class);
System.out.println("context id : " + applicationContext.getId());
String[] beanNames = applicationContext.getBeanNamesForType(TestImport.class);
System.out.println("Bean Name is : " + Arrays.toString(beanNames));
TestImport bean = applicationContext.getBean(TestImport.class);
System.out.println("TestImport bean : " + bean);
applicationContext.close();
}
}
spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c
Bean Name is : [com.spring.study.ioc.register.TestImport]
TestImport bean : TestImport(id=@Import)
通过简单使用@Import
注解,便可以将一个普通的javaBean注册到spring容器中。并且我们可以看到,通过@Import
注解默认注册的组件名称为该javaBean的全类名
@Import 导入 配置类
使用@Import
注解导入配置类,就会将配置类中的所有组件注册到spring容器中。在spring中,并不是@Configuration
标注的类才是配置类,但是被@Configuration
标注的类会被生成代理对象,spring注入时与不使用@Configuration
注解有很大区别,后续会单独说明此处内容,本文不在赘述。
/**
* spring组件配置类
*/
//@Configuration 使用@Import导入时,此注解可以不加
public class TestConfiguration {
@Bean
public TestImport testImport() {
return new TestImport();
}
@Bean
public TestImport testImport2() {
return new TestImport();
}
}
@Import
注解中指定待导入的配置类
/**
* spring 容器启动引导类
*/
@Import(TestConfiguration.class)
public class TestImportBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TestImportBootstrap.class);
System.out.println("context id : " + applicationContext.getId());
String[] beanNames = applicationContext.getBeanNamesForType(TestImport.class);
System.out.println("Bean Name is : " + Arrays.toString(beanNames));
TestImport bean = (TestImport) applicationContext.getBean("testImport");
System.out.println("TestImport bean : " + bean);
applicationContext.close();
}
}
spring容器启动后,配置类中的注解同样会被注册到spring容器中:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c
Bean Name is : [testImport, testImport2]
TestImport bean : TestImport(id=@Import)
由结果可以看出,此时注册的组件名称即为配置类中指定的组件名称,并且通过配置类,可以一次导入多个组件。
@Import 通过ImportSelector 注册
在ImportSelector
接口中只定义了一个接口selectImports
,通过此接口返回需要注册的JavaBean的全类名数组,在使用@Import
导入时,会将接口返回的所有类注册到spring容器中
/**
* 通过 ImportSelector 接口注册组件
*/
@Data
public class TestSelector {
private String id = "@Import:ImportSelector";
}
自定义实现ImportSelector
接口
/**
* 自定义组件选择器,通过返回需要注册的bean的全类名,进行快速的在IOC容器中注册组件
*/
public class CustomImportSelector implements ImportSelector {
/**
* @param importingClassMetadata 标注了@Import配置类上面所有的注解信息
*/
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{TestSelector.class.getName()};
}
}
@Import
注解中指定ImportSelector实现类
/**
* spring 容器启动引导类
*/
@Import(CustomImportSelector.class)
public class TestImportBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TestImportBootstrap.class);
System.out.println("context id : " + applicationContext.getId());
TestSelector bean = applicationContext.getBean(TestSelector.class);
System.out.println("TestSelector bean : " + bean);
String[] beanNames = applicationContext.getBeanNamesForType(TestSelector.class);
System.out.println("bean names:" + Arrays.asList(beanNames));
applicationContext.close();
}
}
spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@238e0d81
TestSelector bean : TestSelector(id=@Import:ImportSelector)
bean names:[com.spring.study.ioc.register.TestSelector]
由结果可以看出,TestSelector
被注册到了spring容器中。与前面的直接注册相比,并没有看出ImportSelector
接口的突出特性。本文只是简单的说明ImportSelector
接口具有注册组件的功能,对于spring容器在启动时,如何执行BeanDefinitionRegistryPostProcessor
来调用selectImports
方法;如何使用ImportSelector
接口实现更复杂的注册功能,将在后续文章中深入理解。
@Import 通过ImportBeanDefinitionRegistrar 注册
在ImportBeanDefinitionRegistrar
接口中只定义了一个registerBeanDefinitions
方法,在此方法中,可以获取到BeanDefinitionRegistry
对象,利用此对象,即可手动将需要的组件注册的spring容器中。在使用BeanDefinitionRegistry
对象时,还可以指定组件在spring容器中注册的bean名称。
/**
* 通过 ImportBeanDefinitionRegistrar 接口手动注册组件
*/
@Data
public class TestRegistrar {
private String id = "@Import:TestRegistrar";
}
自定义实现ImportBeanDefinitionRegistrar
接口
/**
* 手动注册组件到IOC容器中
*/
public class CustomImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
/**
* @param importingClassMetadata 标注了@Import配置类上面所有的注解信息
* @param registry BeanDefinition注册器,可以通过此registry手动的向容器中注册指定的组件
*/
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition("testRegistrar")) {
BeanDefinition definition = new RootBeanDefinition(TestRegistrar.class);
registry.registerBeanDefinition("testRegistrar", definition);
}
}
}
@Import
注解中指定ImportBeanDefinitionRegistrar实现类
/**
* spring 容器启动引导类
*/
@Import(CustomImportBeanDefinitionRegistrar.class)
public class TestImportBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TestImportBootstrap.class);
System.out.println("context id : " + applicationContext.getId());
TestRegistrar bean = applicationContext.getBean(TestRegistrar.class);
System.out.println("TestRegistrar bean : " + bean);
String[] beanNames = applicationContext.getBeanNamesForType(TestSelector.class);
System.out.println("bean names:" + Arrays.asList(beanNames));
applicationContext.close();
}
}
spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@238e0d81
TestRegistrar bean : TestRegistrar(id=@Import:TestRegistrar)
bean names:[testRegistrar]
由此可以看出,TestRegistrar
被注册到了spring容器中。与ImportSelector
接口一样,在spring容器启动时,通过BeanDefinitionRegistryPostProcessor
来执行接口方法。
@Import同时指定多种接口注册
上面的例子中分别说明了使用@Import
,通过直接导入Bean class,配置类,ImportSelector
接口,ImportBeanDefinitionRegistrar
接口来向spring容器中注册组件。当然在使用@Import
注解时,可以同时指定上面的任意几种方式进行注册
/**
* spring 容器启动引导类
*
* @author TangFD
* @since 2019/6/25.
*/
@Import({
TestComponent.class,
TestConfiguration.class,
CustomImportSelector.class,
CustomImportBeanDefinitionRegistrar.class
})
public class TestImportBootstrap {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(TestImportBootstrap.class);
System.out.println("context id : " + applicationContext.getId());
String[] beanNames = applicationContext.getBeanDefinitionNames();
System.out.println("bean names:" + Arrays.asList(beanNames));
applicationContext.close();
}
}
spring容器启动后,控制台打印的结果:
context id : org.springframework.context.annotation.AnnotationConfigApplicationContext@238e0d81
bean names:[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, testImportBootstrap, com.spring.study.ioc.register.TestComponent, com.spring.study.ioc.register.TestConfiguration, testImport, testImport2, com.spring.study.ioc.register.TestSelector, testRegistrar]
向spring容器中注册组件的方式有很多,本文主要说明了如何使用@Import
注解向spring容器中注册组件。并且遗留了一个需要深入理解的知识点:在spring容器启动时,如何通过执行BeanDefinitionRegistryPostProcessor
来执行ImportSelector
和ImportBeanDefinitionRegistrar
接口方法进行组件注册。此处内容,将在后续的spring容器启动过程中,分析BeanFactoryPostProcessor
接口执行过程里进行补充。
学习永远都不是一件简单的事情,可以有迷茫,可以懒惰,但是前进的脚步永远都不能停止。
不积跬步,无以至千里;不积小流,无以成江海;
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK