Spring bean到底是如何创建的?(上)(一)
前言
一、Spring Bean 元信息读取阶段
二、 Spring Bean 注册阶段
三、bean的获取
四、bean的实例化阶段
1) bean class 的加载阶段
2) bean实例化之前阶段
3) bean实例化阶段
4) bean实例化之后阶段
总结
前言:众所周知,spring对于java程序员来说是一个及其重要的后端框架,几乎所有的公司都会使用的框架,而且深受广大面试官的青睐。所以本文就以常见的一个面试题"spring bean的生命周期"为切入点,从源码的角度带领大家来看一看 spring bean到底是如何创建的 。spring bean的生命周期非常重要 ,因为几乎所有的跟spring整合的框架,比如说mybatis 、dubbo 等框架基本上都是通过bean的生命周期来实现跟spring的整合。后面我也会单独写文章,剖析mybatis源码以及是怎么跟spring整合,dubbo我也可能会出一些文章,剖析dubbo3.0的源码。如果有可能的话,spring cloud 源码我也会讲解的,当然这都是以后的打算了。
本文是基于spring源码的5.1版本
在讨论spring创建bean的源码之前,我先大概介绍一下spring的ioc和aop的概念。
ioc(Inversion of Control,缩写为IoC)就是控制翻转的意思,简单来说就是你按照spring提供的配置bean的方式将bean的创建流程交给spring来完成,比如以xml的方式声明bean,以@Bean的注解声明bean,以@Componet注解方式声明bean,当你用这些方式来声明bean的时候,spring在启动的时候就知道要为这个类创建一个对象,接下来spring会按照自己的流程来一步一步完成bean的生成过程,也就是本文的主题,spring bean的创建流程。
aop(Aspect Oriented Programming)英文意思就是面向切面编程,说白了其实就是一个动态代理的过程,只不过spring将生成动态代理的过程给封装到框架的内部,开发者其实只需要声明一下对哪个对象的哪个方法进行代理(pointcut)和在被代理的方法该执行什么样的代码(advice),这样就实现了aop。
有时大家可能会很好奇怎么实现动态代理的过程,怎么我配置了一下切面,就给我代理了呢?我给大家简单解释一下,aop的实现离不开ioc,当在spring bean创建的过程,在某个环节(后面会说到)spring框架会去判断,你有没有配置过给创建的对象进行代理,怎么判断很简单,就是根据你配置的切点表达式判断一下,如果有就给你创建一个代理对象返回给你,这样你拿到的就是代理对象,接下来你对这个对象方法调用就会走你写的那个advice所对应的代码,如果判断没有,就会返回给你原来的对象,就这么简单。
大家不妨去了解一下静态代理,这会有助于大家了解动态代理,动态代理其实跟静态代理差不多,只不过静态代理需要你手动写对象的代理,属于硬编码的方式,有多少个类就得写多少个类的代理类,很麻烦,而动态代理是动态生成代理类,但是本质都是加一些特殊的功能,这里就不再过多赘述了。
好了说完了spring ioc和aop的基本概念之后,接下来就来进入spring ioc中的bean的生命周期源码分析。
一、Spring Bean 元信息(BeanDefinition)读取阶段
spring容器刚启动的时候,spring会按照你的声明bean的方式(以xml的方式声明bean,以@Bean的注解声明bean,以@Componet注解方式声明bean等(其实也可以通过Properties资源配置))去读取你声明的信息,然后封装在一个叫BeanDefinition对象里面,BeanDefinition可以看成你配置信息的一个封装对象,就跟你平时new的User是一个概念,后面在创建对象的时候,spring拿出来BeanDefinition,基于你配置的信息来创建对象。
二、 Spring Bean 注册阶段
Spring Bean 元信息读取阶段结束后会为每一个bean生成一个BeanDefinition,你配置了那么多的bean就有那么多BeanDefinition吧,怎么都得有一个地方存吧,可以很好想到的,java中数据结构还是很多的,比如说list,map等,所以spring选择通过map来存,只不过spring考虑的比较完善,封装了一个类,叫BeanDefinitionRegistry,直接实现就是DefaultListableBeanFactory这个类(这个类是spring ioc核心类,是BeanFactory基本上算是唯一的实现,非常非常的重要),通过registerBeanDefinition方法进行注册
在此为止,你通过xml或者各种方式声明的bean已经注册到ioc容器中了,所谓的注册,就是表明,这些对象需要spring来帮你创建,虽然你只配置了一下,但是spring得去做很多的事来读取配置。所以接下来就是通过spring 来获取到你注册bean,就会进入spring bean的创建阶段
三、bean的获取阶段
为什么先讲获取。因为spring源码中是先从ioc容器中获取对象,获取不到再创建的。所以这里先从DefaultListableBeanFactory的doGetBean方法入手,它会委派给它的父类来处理
先根据getSingleton方法去获取对象 ,这里就牵扯出三级缓存解决循环依赖的问题.。
文章转自公众号:三友的java日记