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来执行ImportSelectorImportBeanDefinitionRegistrar接口方法进行组件注册。此处内容,将在后续的spring容器启动过程中,分析BeanFactoryPostProcessor接口执行过程里进行补充。

学习永远都不是一件简单的事情,可以有迷茫,可以懒惰,但是前进的脚步永远都不能停止。

不积跬步,无以至千里;不积小流,无以成江海;

Spring Framework 组件注册 之 @Import的更多相关文章

  1. Spring Framework 组件注册 之 FactoryBean

    Spring Framework 组件注册 之 FactoryBean 前言 前两篇文章介绍了如何使用@Component,@Import注解来向spring容器中注册组件(javaBean),本文将 ...

  2. Spring Framework 组件注册 之 @Component

    Spring Framework 组件注册 之 @Component 写在前面 在spring大行其道的今天,对于spring的使用和掌握乃是不可缺少的必备技能.但是spring的整个体系尤为庞大,对 ...

  3. spring注解-组件注册

    一.@Configuration+@Bean @Configuration:配置类==配置文件 @Bean:给容器中注册一个Bean:类型为返回值的类型,默认是用方法名作为id @Bean(" ...

  4. Spring笔记 - 组件注册

    @Bean:类注入容器 xml方式: <bean id="person" class="com.hrh.bean.Person"> <prop ...

  5. 一、Spring之组件注册-@Configuration&@Bean给容器中注册组件

    xml配置方式 首先我们创建一个实体类Person public class Person { private String name; private Integer age; private St ...

  6. Spring Framework 条件装配 之 @Conditional

    Spring Framework 条件装配 之 @Conditional 前言 了解SpringBoot的小伙伴对Conditional注解一定不会陌生,在SpringBoot项目中,Conditio ...

  7. 向Spring容器中注册组件的方法汇总小结

    1.通过xml定义 <bean class=""> <property name="" value=""></ ...

  8. spring注解扫描组件注册

    最近对单点系统进行微服务拆分,被各个springboot的组件注册搞得云里雾里的.(有的是通过springboot的自动配置进IOC容器的,有的是自己添加构造方法添加进IOC容器.)决定抽时间将spr ...

  9. Spring注解开发-全面解析常用注解使用方法之组件注册

    目录 1. @Configuration 2. @ComponentScan excludeFilters includeFilters 使用自定义TypeFilter 3. @Bean @Scope ...

随机推荐

  1. twemproxy接收流程探索——剖析twemproxy代码正编

    本文旨在帮助大家探索出twemproxy接收流程的代码逻辑框架,有些具体的实现需要我们在未来抽空去探索或者大家自行探索.在这篇文章开始前,大家要做好一个小小的心理准备,由于twemproxy代码是一份 ...

  2. 解决用户绕过Servlet直接访问jsp页面

    解决用户绕过ActionServlet,直接访问jsp文件的问题 1.将所有jsp文件拷贝到WEB-INF目录下 因为WEB-INF目录中的内容不能直接访问,但能转发过来 项目结构图如下: 2.修改s ...

  3. 在MVC项目中分页使用MvcPager插件

    参考网站  http://www.webdiyer.com/mvcpager/demos/ 这个插件非常简单易用,如果想快速使用 可以参考我这篇文章,其实参考网站也是非常简单的 首先选择你的web项目 ...

  4. nginx 502错 failed (13: Permission denied)

    安装nginx和php-fpm之后出现502错误 找了个理由说php-fpm不启动 ,但在我的实践中,该过程开始 找了半天没找到病因.视图nginx记录后 我发现下面的错误 [crit] 2686#0 ...

  5. windows 系统文件 —— 特殊文件及文件类型

    0. .mht 文件(MHTML) MHTML文件又称为聚合 HTML 文档.Web 档案或单一文件网页(聚合成单一文件).单个文件网页可将网站的所有元素(包括文本和图形)都保存到单个文件中.这种封装 ...

  6. CSS position财产

    CSS在position位置信息要素用于表示属性. 有三个起飞值:static, absolute, relative. 假设元件不显式配置position财产,该元素默认position 值至sta ...

  7. StackLayout

    堆栈式地放置内容可以在xaml中完成视图,也可以在cs代码中完成视图 Xamarin的所有视图和布局都是可以 1.在xaml中完成 2.在cs代码中完成视图 (类比WPF) 示例 在cs代码中完成视图 ...

  8. Win10《芒果TV》更新v3.4.10春光版:优化弹窗体验,修复热键和推送

    春来触地故乡情,忽见风光忆两京,金谷踏花香骑入,曲江碾草钿车行,Win10版<芒果TV>更新v3.4.10,进一步优化弹窗体验,修复热键和推送异常. Win10版<芒果TV>V ...

  9. 腾讯QQ 8.9.3体验版发布 在线文档多端同步实时保存

    感谢N软网的投递 腾讯体验中心迎来QQ8.9.3首个维护体验版发布,详细版本号为v8.9.3.21006,上一个体验版v8.9.2.20717发布于4月20日,时隔34天又迎来了更新.本次升级主要是在 ...

  10. c#利用IronPython调用python的过程种种问题

    c#利用IronPython调用python的过程种种问题 小菜鸟一枚,最新学习了Python,感觉语言各种简短,各种第三方类库爽歪歪,毕竟之前是从c#转来的,看到Python的request类各种爽 ...