当前位置: 首页 > 科技观察

面试惊喜:说说Spring中Bean的生命周期?

时间:2023-03-19 14:11:48 科技观察

作者|雷哥来源|Java面试题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)Java中的公共类称为Bean或JavaBean,Spring中的Bean是指对象的生命周期是一个被管理的对象通过SpringIoC容器。因此,在使用Spring中的Bean对象时,不需要通过new来创建对象,只需要使用DI(DependencyInjection)从Spring中提取要使用的对象即可。那么Spring中bean的生命周期是怎样的呢?接下来,我们一起来看看吧。1.Bean生命周期Spring中bean的生命周期是指Spring中一个bean从创建到销毁的整个过程(IoC)。Spring中Bean的生命周期主要包括以下五个部分:实例化:为Bean分配内存空间。设置属性:注入并组装当前类所依赖的Bean属性。初始化:执行各种通知。执行初始化的前置方法。执行初始化方法。Post方法执行初始化。使用Bean:在程序中使用Bean对象。DestroyBean:销毁Bean对象。在上面的生命周期中,需要注意的是“实例化”和“初始化”是两个完全不同的过程。不要混淆他们。实例化只是为Bean分配内存空间,而初始化则是程序的执行。权限,从系统级切换到用户级,开始执行用户添加的业务代码。2.代码演示接下来,我们将使用SpringBoot中的代码来为大家展示Bean的生命周期。PS:由于SpringBoot是基于Spring创建的,Bean在Spring或SpringBoot中的行为是一致的,而SpringBoot是目前主流的框架,所以本文使用SpringBoot来演示Bean的生命周期。首先,我们创建一个名为BeanLifeComponent的Bean对象(类名无所谓,可以随意指定),其具体实现代码如下:importorg.springframework.beans.factory.BeanNameAware;importorg.springframework。stereotype.Component;importjavax.annotation.PostConstruct;importjavax.annotation.PreDestroy;@ComponentpublicclassBeanLifeComponentimplementsBeanNameAware{publicvoidsetBeanName(Strings){System.out.println("执行BeanName的通知方法");}@PostConstructpublicvoidpostConstruct(){System.out.println("执行初始化方法");}publicvoiduse(){System.out.println("UseBean");}@PreDestroypublicvoidpreDestroy(){System.out.println("执行销毁方法");}}然后,我们创建一个MyBeanPostProcessor类(类名无所谓,可以随意指定)来实现前置初始化方法和后置初始化方法。具体实现代码如下:importorg.springframework。beans.BeansException;importorg.springframework.beans.factory.config.BeanPostProcessor;importorg.springframework.stereotype.Component;@Componentpublic类MyBeanPostProcessor实现BeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{if(beanName.equals("beanLifeComponent")){System.out.println("执行预初始化方法");}返回豆;}@OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{if(beanName.equals("beanLifeComponent")){System.out.println("后初始化方法");}返回豆;}}为什么要单独创建一个类来执行预初始化方法和后初始化方法呢?这是因为初始化的pre-method和post-method是为所有的bean服务的,不是为某个bean服务的,所以这两个方法不能写在特定的bean中,否则(这两个方法)不会执行最后在SpringBoot的启动类中获取Bean。具体实现代码如下:args){//获取上下文对象并启动SpringBoot项目ConfigurableApplicationContextcontext=SpringApplication.run(DemoApplication.class,args);//获取BeanBeanLifeComponentcomponent=context.getBean(BeanLifeComponent.class);//使用Beancomponent.use();//停止SpringBoot项目context.close();}}上述程序最终的执行结果如下图所示:从上面的执行结果可以看出,代码执行顺序Executionsequence符合Bean的生命周期:Instantiation:为Bean分配内存空间。设置属性:注入并组装当前类所依赖的Bean属性。初始化:执行各种通知。执行初始化的前置方法。执行初始化方法。Post方法执行初始化。使用Bean:在程序中使用Bean对象。DestroyBean:销毁Bean对象。那么问题来了,我们能不能先初始化,再设置属性呢?也就是调换生命周期中第2步和第3步的执行顺序?答案是否定的。想象一个场景,如果在初始化方法中使用了注入对象的一个??方法,比如下面的代码:@ControllerpublicclassUserController{@ResourceprivateUserServiceuserService;@PostConstruct//初始化方法publicvoidpostConstruct(){userService.sayHi();}}此时如果先执行步骤2,将UserService注入到当前类中,再调用步骤3进行初始化,则程序执行正常。但是,如果第2步和第3步的执行顺序是交互的,那么程序执行就会报错(空指针异常),所以Bean的生命周期顺序必须是:1.实例化:为分配内存空间豆子;2.设置属性:注入并组装当前类所依赖的Bean属性;3.初始化:执行各种通知。执行初始化的前置方法。执行初始化方法。Post方法执行初始化。4.UseBean:在程序中使用Bean对象;5.DestroytheBean:销毁Bean对象。小结Bean的生命周期是指一个Bean在Spring(IoC)中从创建到销毁的整个过程。一个bean的生命周期主要包括以下五个过程:1.实例化:为bean分配内存空间;2、设置属性:注入并组装当前类所依赖的bean属性;3.初始化:执行各种通知。执行初始化的前置方法。执行初始化方法。Post方法执行初始化。4.UseBean:在程序中使用Bean对象;5.DestroytheBean:销毁Bean对象。