面试官:聊一聊Spring实例化Bean都有哪些方式?

createh54个月前 (01-11)技术教程38

Spring功能简介

我们都知道Spring是一个ioc容器,它主要给我们提供ioc,aop以及依赖注入功能,通过spring我们在应用中并不需要了解对象如何创建,这个都交给spring容器去管理。通过简单的声明式配置就可完成对象的装配,可以简单的理解成Spring内部就是一个很大的Map,里面存储了很多实例化好的java对象,我们需要的时候制需要getBean 或者通过属性,setter,构造器,接口 等自动注入方式直接依赖其他的Bean。Spring容器表面看起来非常的简单,但是它内部实际上是一个非常复杂的过程,Spring的源码非常的庞大,分支和接口也非常多,本节不说源码,只是简单的和大家分享Spring的核心流程和Bean创建的几种方式。看完后你一定对Spring创建Bean的过程有更深的理解。

Spring容器bean创建流程

spring容器创建Bean的过程非常复杂,这里我通过一个图简单的把Bean创建的核心流程画出来,有助于大家可用进一步了解Bean创建的过程。

上图可用看到,Spring创建bean主要经过四个流程

  1. 资源定位 ,可从xml配置文件,java注解,java配置类等各种入口加载bean的来源
  2. 加载解析,将各种入口资源解析成BeanDefinition
  3. 注册,将第二步解析出来的各种BeanDefinition注册到BeanDefinition容器中等待实例化
  4. 实例化,将BeanDefinition容器中的BeanDefinition实例化成最终的Bean对象

其中在BeanDefinition到Bean的过程中需要经过BeanFactoryPostProcessor前置处理器,在Bean实例化前可以对BeanDefinition进行修改,创建Bean后会通过BeanPostProcessor后置处理器对Bean进行修改或者进一步包装。很多优秀的框架都是基于前置和后置处理器对Spring做二次扩展,实现了很多强大的功能,特别是SpringBoot在这方面更是突出的代表。

Bean的创建方式

通过上面对Bean创建流程的分析后,大概就清楚在具体应用中我们到底有那些方式可用创建Bean了,实际应用中主要可用通过以下几个方式创建Bean.

  1. 通过注解扫描方式

我们常见的 @Component,@Service,@Controller,@Configuration 这几个注解都被Spring扫描到并自动注入到容器,其中后面三个其实就是@Component,只不过从名字上区分不同类别而已。

  1. 其次用@import导入配置类,这种配置方式就是直接导入一个类进行配置,比如我们非常熟悉的 @EnableAsync,@EnableScheduling 这两个注解内部就是通过@import导入的。
  2. 直接使用BeanDefinitionRegistry接口,通过编程的方式自定义BeanDefinition后注入到容器。

总结

注解扫描的方式多用于本项目默认扫描的包路径,比如@SpringBootApplication注解所在的包路径下才能被扫描到。

@import用于导入不在默认扫描路径下的配置类,比如一些外部的第三方包

前面两种都是通过声明式方式配置Bean,这两种方式都在容器启动后Bean初始化完成了。通过BeanDefinitionRegistry接口可以动态的创建Bean,比如在运行的过程中创建Bean并交给Spring托管,这种方式最灵活。比如我们可以根据配置文件动态的创建多个数据源,也可以在各种数据源管理应用运行的过程中再创建数据源,其实Spring底层最终都是通过这个接口注册BeanDefinition的。

相关文章

spring阅读--容器及实例化

鲁班学院:戴明智(D55)从今天开始,我们一起过一遍Spring的官网,一边读,一边结合在课堂上学习的知识,讲一讲自己的理解。不管是之前关于动态代理的文章,还是读Spring的官网,都是为了之后对Sp...

长篇图解java反射机制及其应用场景

一、什么是java反射?在java的面向对象编程过程中,通常我们需要先知道一个Class类,然后new 类名()方式来获取该类的对象。也就是说我们需要在写代码的时候(编译期或者编译期之前)就知道我们要...

Java并发编程吐血1个月总结最全面的100道面试题

目录一、大部分人对Java并发仍停留在理论阶段二、中间件系统的内核机制:双缓冲机制三、百万并发的技术挑战四、内存数据写入的锁机制以及串行化问题五、片机制 + 分段加锁机制六、缓冲区写满时的双缓冲交换七...