前言SpringBean的生命周期,面试的时候很容易问到。这不,前段时间有个粉丝去字节跳动面试,因为这个问题他答不上来,他也一直没做。如果只讲基础,感觉和网上大部分文章没什么区别,但是我想写的更深入一点。考虑到很多同学不喜欢看源码,所以我把文章分为两部分。前面部分是基础知识,主要方便大家面试学习。后面的部分是源代码部分。对源码感兴趣的同学可以继续往后看。1.基础知识1.1什么是IoC?IoC,inversionofcontrol,大家要知道,所谓控制反转就是把新对象的权限交给容器,所有的对象都由容器来控制,这就是所谓的控制反转.IoC很好地体现了面向对象的设计法则之一——好莱坞法则:“不要找我们,我们来找你”,即IoC容器帮助对象找到对应的依赖对象并注入,而不是主动寻找它的对象。理解好IoC的关键是要弄清楚“谁控制谁,控制什么,为什么要反转(有反转就应该有正转),哪些方面是反转的”。谁控制谁和什么?在传统的JavaSE编程中,我们直接在对象内部通过new创建对象,程序主动创建依赖对象。IoC通过一个特殊的容器来创建这些对象,即IoC容器控制着对象的创建。谁控制谁?当然IoC容器控制对象;控制什么?主要控制外部资源(不仅仅是对象,比如包含文件等)的获取。为什么反了,反了哪些方面?哪里有逆转,哪里就有正向转变。传统应用中,我们在对象中主动控制直接获取依赖对象,即正向转化,而反向是容器帮助创建和注入依赖对象。为什么会反过来呢?因为容器帮我们找到并注入了依赖对象,对象只是被动接受依赖对象,所以反过来了;哪些方面是相反的?依赖对象的获取是相反的。1.2Bean生命周期对于PrototypeBean,当用户getBean获取PrototypeBean实例后,IOC容器不再管理当前实例,而是将管理权交给用户,然后getBean生成新的实例。所以我们在描述Bean的生命周期时,都是指SingletonBean。Bean生命周期过程:实例化:第一步,实例化一个bean对象;属性赋值:第2步,为bean设置相关属性和依赖;初始化:初始化阶段有很多步骤,其中第5、6步是真正的初始化,第3、4步在初始化前执行,第7步在初始化后执行。初始化完成后,就可以使用Bean了;销毁:步骤8~10,步骤8其实也可以算作销毁阶段,但不是真正意义上的销毁,而是在使用前注册销毁的相关调用接口,然后在真正销毁Bean的时候执行相应的方法在后面的步骤9和10中。整个执行过程有点抽象。下面我们用代码来演示执行过程。1.3执行流程创建一个LouzaiBean。publicclassLouzaiBeanimplementsInitializingBean,BeanFactoryAware,BeanNameAware,DisposableBean{/***name*/privateStringname;publicLouzaiBean(){System.out.println("1.调用构造函数:我出生了!");}publicStringgetName(){返回名称;}publicvoidsetName(Stringname){this.name=name;System.out.println("2.设置属性:我的名字是"+name);}@OverridepublicvoidsetBeanName(Strings){System.out.println("3.调用BeanNameAware#setBeanName方法:我要上学了,我有一个学名");}@OverridepublicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{System.out.println("4.调用BeanFactoryAware#setBeanFactory方法:学校被选中");}@OverridepublicvoidafterPropertiesSet()throwsException{System.out.println("6.InitializingBean#afterPropertiesSet方法:注册");}publicvoidinit(){System.out.println("7.自定义初始化方法:努力上学");}@Overridepublicvoiddestroy()throwsException{System.out.println("9.DisposableBean#destroymethod:沉闷的生活结束了");}publicvoiddestroyMethod(){System.out.println("10.自定义销毁方法:睡眠,不要试图唤醒我");}publicvoidwork(){System.out.println("正在使用的Bean:工作,只有那些没用的到社会度假。”);}}定制一个后处理器MyBeanPostProcessor。publicclassMyBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println("5.BeanPostProcessor.postProcessBeforeInitialization方法:在学校注册");返回@OverObject贝弗兰;}postProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println("8.BeanPostProcessor#postProcessAfterInitialization方法:我终于毕业了,拿到了毕业证!");返回豆;}}applicationContext.xml配置文件(部分)。测试入口:publicclassMyTest{publicstaticvoidmain(String[]args){ApplicationContextcontext=newClassPathXmlApplicationContext("classpath:applicationContext.xml");LouzaiBeanlouzaiBean=(LouzaiBean)context.getBean("louzaiBean");louzaiBean.work();((ClassPathXmlApplicationContext)上下文).destroy();}}执行结果:1.调用构造函数:我出生了!2.设置属性:我叫楼仔3.调用BeanNameAware#setBeanName方法:我要上学了,学名4.调用BeanFactoryAware#setBeanFactory方法:选择学校5.BeanPostProcessor.postProcessBeforeInitialization方法:在学校注册6.InitializingBean#afterPropertiesSet方法:注册7.自定义init方法:努力上学8.BeanPostProcessor#postProcessAfter初始化方法:终于毕业了,拿到文凭了!Beaninuse:工作,只有对社会没有用处的人才放假。9.DisposableBean#destroy方法:平凡的生活结束了。10.自定义销毁方法:睡觉,不要试图叫醒我。这个过程很清晰,和Bean生命周期流程图完全可以匹配。1.4扩展方法我们发现在整个生命周期中有很多扩展过程,大致可以分为四类:Aware接口:允许Bean获取容器的一些资源,比如BeanNameAware的setBeanName(),setBeanFactory()BeanFactoryAware;post-processor:做一些前处理和后处理,比如BeanPostProcessor的postProcessBeforeInitialization()和postProcessAfterInitialization();生命周期接口:定义初始化方法和销毁方法,如InitializingBean的afterPropertiesSet(),DisposableBean的destroy();配置生命周期方法:可以通过配置文件自定义初始化和销毁??方法,比如配置文件配置的init()和destroyMethod()。2.源码解读注意:Spring版本是5.2.15.RELEASE,否则和我的代码不一样!!!以上知识其实网上都有。以下是我们的亮点。让您跟随我完成代码过程。2.1代码入口这里需要多跑几次,跳过前面的beanName,只看louzaiBean。进入doGetBean(),getSingleton()没有找到对象,进入创建Bean的逻辑。2.2实例化后进入doCreateBean(),调用createBeanInstance()。进入createBeanInstance()后,调用instantiateBean()。进入实例LouzaiBean的方法,实例化LouzaiBean。2.3属性赋值然后返回doCreateBean(),继续往回走,进入populateBean()。这个方法很重要,其实就是依赖注入的逻辑。进入populateBean()后,执行applyPropertyValues()进入applyPropertyValues(),执行bw.setPropertyValues()进入processLocalProperty(),执行ph.setValue()。进入实例LouzaiBean的方法,给LouzaiBean赋名。此时执行populateBean(),下面会初始化Bean。2.4初始化我们继续回到doCreateBean(),然后执行initializeBean()。进入实例LouzaiBean的方法,为LouzaiBean设置BeanName。回到invokeAwareMethods()。进入实例LouzaiBean的方法,为LouzaiBean设置BeanFactory。第一次回到initializeBean(),执行下面的逻辑。这里需要循环几次才能找到MyBeanPostProcessor的策略方法。我们自己定义的后处理方法。第二次回到initializeBean(),执行如下逻辑。进入实例LouzaiBean的方法,实现afterPropertiesSet()。返回invokeInitMethods()并执行以下逻辑。输入invokeCustomInitMethod()并执行以下逻辑。进入实例LouzaiBean的方法,执行init()。第三次回到initializeBean(),执行如下逻辑。我们自己定义的后处理方法。至此,初始化过程就全部结束了,一切都围绕initializeBean()展开。2.4销毁louzaiBean生成后,后面会进行销毁操作,整个过程会比较简单。进入实例LouzaiBean的方法,执行destroy()。回到destroy()并执行以下逻辑。进入实例LouzaiBean的方法,执行destroyMethod()。至此,所有流程结束。文章详细描述了代码的所有逻辑流程。大家可以根据上面的逻辑自行调试。3、写到最后,我们来回顾一下几个重要的方法:doCreateBean():这个是入口;createBeanInstance():用于初始化Bean,会调用对象的构造函数;populateBean():属性对象的依赖注入,以及成员变量初始化;initializeBean():里面有4个方法,先执行awareBeanNameAware、BeanFactoryAware接口;然后执行BeanPostProcessor前端接口;然后执行InitializingBean接口,配置好的init();最后执行BeanPostProcessor后置接口。destroy():先执行DisposableBean接口,再执行配置的destroyMethod()。对于populateBean(),里面的核心其实就是对象依赖注入,这也是经常考的知识点,比如循环依赖