0


面试题-Spring Bean的生命周期

文章目录

Spring Bean 生命周期分为哪几个阶段

在这里插入图片描述

  1. 实例化:Spring 容器通过调用构造函数来创建 Bean 的实例。在这个阶段,Spring 还会根据配置文件或者注解来决定 Bean 的具体实现类。
  2. 填充属性:在 Bean 实例化之后,Spring 会将配置文件中定义的属性注入到 Bean 实例中。这些属性可以是简单的数据类型,也可以是其他 Bean 的引用,具体取决于 Bean 的定义和注解配置。
  3. 初始化:- @PostConstruct 注解的方法:如果 Bean 类中有使用 @PostConstruct 注解的方法,Spring 会在填充属性之后调用这些方法。这个阶段通常用于 Bean 的初始化逻辑。- InitializingBean 接口:如果 Bean 实现了 InitializingBean 接口,Spring 会调用 afterPropertiesSet() 方法来进行初始化。- init-method 配置:在 XML 配置中,如果定义了 init-method,Spring 会在填充属性之后调用指定的方法进行初始化。
  4. 使用:在 Bean 完成初始化之后,Spring 容器就可以将其交给应用程序使用了。这个阶段是 Bean 的正常工作阶段。
  5. 销毁:- @PreDestroy 注解的方法:如果 Bean 类中有使用 @PreDestroy 注解的方法,Spring 会在 Bean 销毁之前调用这些方法。这个阶段用于进行 Bean 的清理工作。- DisposableBean 接口:如果 Bean 实现了 DisposableBean 接口,Spring 会调用 destroy() 方法来进行销毁操作。- destroy-method 配置:在 XML 配置中,如果定义了 destroy-method,Spring 会在 Bean 销毁之前调用指定的方法进行清理。

Bean详细生命周期过程:
在这里插入图片描述


浅析Bean生命周期源码实现

以下是精简代码:

1.1 DefaultListableBeanFactory

DefaultListableBeanFactory是Spring的核心BeanFactory实现,它负责Bean的创建和管理。在这个类中,Bean实例化的过程主要通过getBean方法来触发。

public<T>TgetBean(Class<T> requiredType)throwsBeansException{returndoGetBean(null,null, requiredType,false);}publicObjectgetBean(String name)throwsBeansException{returndoGetBean(name,null,null,false);}

在doGetBean方法中,Spring会检查Bean是否已经存在于缓存中。如果不存在,则会调用createBean方法进行实例化。

protected<T>TdoGetBean(String name,Class<T> requiredType,Object[] args,boolean typeCheckOnly){// 省略部分逻辑if(bean !=null){return(T) bean;}return(T)createBean(beanName, mbd, args);}

1.2 createBean

createBean方法负责Bean的实际实例化过程。首先,Spring会使用反射创建Bean实例。

protected<T>TcreateBean(String beanName,RootBeanDefinition mbd,Object[] args){// 省略部分逻辑BeanWrapper beanWrapper =createBeanWrapper(beanClass);Object beanInstance = beanWrapper.getWrappedInstance();return(T) beanInstance;}

在这个方法中,createBeanWrapper会创建一个BeanWrapper实例,用于包装和操作Bean实例。

protectedBeanWrappercreateBeanWrapper(Object bean){returnnewBeanWrapperImpl(bean);}

2.1 populateBean

populateBean方法负责将Bean的依赖注入到实例中。它会读取BeanDefinition中的属性配置,并将这些属性值注入到Bean实例中。

protectedvoidpopulateBean(String beanName,RootBeanDefinition mbd,BeanWrapper bw){PropertyValues pvs = mbd.getResolvedProps();if(pvs !=null){for(PropertyValue pv : pvs.getPropertyValues()){
            bw.setPropertyValue(pv.getName(), pv.getValue());}}}

3.1 initializeBean

初始化阶段主要由 AbstractAutowireCapableBeanFactory 类中的 initializeBean 方法负责。这个方法会在 DefaultListableBeanFactorycreateBean 方法中被调用。

在这个方法中,首先检查Bean是否实现了InitializingBean接口。如果实现了,则调用其afterPropertiesSet方法。afterPropertiesSet方法中可以包含一些自定义的初始化逻辑,例如检查必需的属性是否被正确设置等。

protectedObjectinitializeBean(String beanName,Object bean,RootBeanDefinition mbd){// 调用 InitializingBean 的 afterPropertiesSet 方法if(bean instanceofInitializingBean){try{((InitializingBean) bean).afterPropertiesSet();}catch(Exception ex){thrownewBeanInitializationException("Initialization of bean failed", ex);}}// 调用用户自定义的初始化方法String initMethodName = mbd.getInitMethodName();if(initMethodName !=null){invokeInitMethod(beanName, bean, mbd);}return bean;}

3.2 invokeInitMethod

invokeInitMethod方法会通过反射调用用户定义的初始化方法。这些方法是通过RootBeanDefinition中的initMethodName属性指定的。

privatevoidinvokeInitMethod(String beanName,Object bean,RootBeanDefinition mbd){String initMethodName = mbd.getInitMethodName();try{Method initMethod = bean.getClass().getMethod(initMethodName);
        initMethod.invoke(bean);}catch(Exception e){thrownewBeansException("Failed to invoke init method '"+ initMethodName +"' on bean with name '"+ beanName +"'", e);}}

invokeInitMethod方法会通过反射查找并调用指定的初始化方法。这个方法通常用于执行一些特定的初始化操作,比如建立数据库连接等

3.3 applyBeanPostProcessorsBeforeInitialization

Spring会在Bean的初始化过程中扫描并执行@PostConstruct注解标记的方法。这一过程通常发生在AbstractAutowireCapableBeanFactory类的applyBeanPostProcessorsBeforeInitialization方法中。

protectedObjectapplyBeanPostProcessorsBeforeInitialization(Object existingBean,String beanName)throwsBeansException{Object result = existingBean;for(BeanPostProcessor processor :getBeanPostProcessors()){
        result = processor.postProcessBeforeInitialization(result, beanName);if(result ==null){returnnull;}}return result;}

在invokeInitMethod方法之前,会调用@PostConstruct注解的方法。
在这里插入图片描述

5.1 destroyBean

destroyBean 方法在 Spring 的 AbstractAutowireCapableBeanFactory 类中定义。它的作用是执行 Bean 销毁前的处理,包括调用 DisposableBean 接口的 destroy 方法和用户自定义的销毁方法。

publicvoiddestroyBean(String beanName,Object bean){// 调用DisposableBean的destroy方法if(bean instanceofDisposableBean){try{((DisposableBean) bean).destroy();}catch(Exception e){thrownewBeansException("Failed to invoke destroy method on bean with name '"+ beanName +"'", e);}}// 调用用户自定义销毁方法String destroyMethodName = mbd.getDestroyMethodName();if(destroyMethodName !=null){invokeDestroyMethod(beanName, bean, mbd);}}

5.2 invokeDestroyMethod

invokeDestroyMethod方法通过反射调用用户定义的销毁方法。

privatevoidinvokeDestroyMethod(String beanName,Object bean,String destroyMethodName){try{Method destroyMethod = bean.getClass().getMethod(destroyMethodName);
        destroyMethod.invoke(bean);}catch(Exception ex){thrownewBeanCreationException("Failed to invoke destroy method '"+ destroyMethodName +"' on bean with name '"+ beanName +"'", ex);}}

Spring Bean的后置处理器是什么?在项目中如何使用它?

Spring Bean 的后置处理器(BeanPostProcessor)是 Spring 框架中的一种机制,用于在 Bean 实例化和初始化的过程中插入自定义逻辑。它允许开发者在 Bean 实例化后、初始化前,和初始化后,执行额外的处理。

使用 BeanPostProcessor
要使用 BeanPostProcessor,需要实现 org.springframework.beans.BeanPostProcessor 接口,并重写 postProcessBeforeInitializationpostProcessAfterInitialization 方法。以下是如何在项目中使用它的步骤:

  1. 创建自定义的 BeanPostProcessor 实现:importorg.springframework.beans.BeansException;importorg.springframework.beans.factory.config.BeanPostProcessor;publicclassCustomBeanPostProcessorimplementsBeanPostProcessor{@OverridepublicObjectpostProcessBeforeInitialization(Object bean,String beanName)throwsBeansException{// 在 Bean 初始化之前进行处理System.out.println("Before Initialization: "+ beanName);return bean;// 返回处理后的 Bean}@OverridepublicObjectpostProcessAfterInitialization(Object bean,String beanName)throwsBeansException{// 在 Bean 初始化之后进行处理System.out.println("After Initialization: "+ beanName);return bean;// 返回处理后的 Bean}
  2. 将自定义 BeanPostProcessor 注册到 Spring 容器中:importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassAppConfig{@BeanpublicCustomBeanPostProcessorcustomBeanPostProcessor(){returnnewCustomBeanPostProcessor();}}

应用场景

  • 动态修改 Bean:在 Bean 初始化后对其进行修改,例如为 Bean 添加额外的属性或功能。
  • 日志记录:记录 Bean 的创建和初始化过程,便于调试和监控。 创建代理:使用 AOP 创建 Bean 的代理对象,以添加额外的功能如事务管理、安全控制等。

Spring Bean的生命周期中,哪些阶段可以介入自定义操作

初始化前

方法:

  • postProcessBeforeInitialization(由 BeanPostProcessor 提供)

应用: 在Bean初始化之前执行额外的处理,例如修改Bean的状态或属性,进行预处理操作。

初始化时

方法:

  • afterPropertiesSet(由 InitializingBean 接口提供)
  • @PostConstruct 注解方法
  • XML 配置中的 init-method 方法

应用: 在Bean的属性设置完成后,执行初始化逻辑,如设置默认值、进行资源准备或配置。

初始化后

方法:

  • postProcessAfterInitialization(由 BeanPostProcessor 提供)

应用: 在Bean初始化之后执行附加处理,例如创建代理对象、添加功能、日志记录等。

销毁前

方法:

  • destroy(由 DisposableBean 接口提供)
  • @PreDestroy 注解方法
  • XML 配置中的 destroy-method 方法

应用: 在Bean销毁之前进行清理操作,例如释放资源、保存状态或关闭连接等。


Spring Bean 的作用域都有哪些?如何控制 Bean 的生命周期?

  1. Singleton(单例)****描述: 默认作用域。Spring容器中只创建一个Bean实例,并在整个容器中共享这个实例。生命周期: 从容器启动到容器关闭期间,Bean实例始终存在。
  2. Prototype(原型)****描述: 每次请求都会创建一个新的Bean实例。每个实例都有独立的生命周期。生命周期: 每次获取Bean时,都会创建一个新的实例。Bean的生命周期从创建开始,到被垃圾回收时结束。
  3. Request(请求)****描述: 每个HTTP请求都会创建一个新的Bean实例。Bean的生命周期与HTTP请求相对应。生命周期: 从每个HTTP请求开始到请求结束,每次请求都会创建一个新的Bean实例。
  4. Session(会话)****描述: 每个HTTP会话创建一个新的Bean实例。Bean的生命周期与HTTP会话相对应。生命周期: 从每个HTTP会话开始到会话结束,每个会话都有一个独立的Bean实例。
  5. GlobalSession(全局会话)****描述: 在Portlet环境中使用。每个全局会话创建一个新的Bean实例。生命周期: 适用于Portlet应用中的全局会话,每个全局会话有一个独立的Bean实例。

例如,配置一个原型作用域的 Bean:

<beanid="myBean"class="com.example.MyBean"scope="prototype"/>

或通过注解@scope 设置

此外,我们还可以自定义 Bean 的初始化和销毁方法,以在 Bean 作用域开始和结束时执行特定逻辑。可以通过 init-methoddestroy-method 属性来指定这些方法:

<beanid="myBean"class="com.example.MyBean"scope="prototype"init-method="start"destroy-method="end"></bean>

Spring中的延迟初始化是什么,如何配置延迟初始化?

在Spring中,延迟初始化(Lazy Initialization)是一种延迟Bean创建的机制,即只有在实际需要Bean时才会创建它,而不是在容器启动时就立即创建。这可以提高应用程序的启动速度和资源利用率,特别是对于那些不常用的Bean。

延迟初始化的配置方式

  1. 通过 @Lazy 注解- 应用场景:在类级别或方法级别使用,表示当Bean首次被使用时才会被创建。- 配置方式: - 在类上:对整个Bean类应用延迟初始化。@Lazy@ComponentpublicclassMyBean{// Bean实现}- 在方法上:对特定的Bean方法应用延迟初始化。@ConfigurationpublicclassAppConfig{@Bean@LazypublicMyBeanmyBean(){returnnewMyBean();}}
  2. 在 XML 配置中- 应用场景:在传统的XML配置中配置延迟初始化。- 配置方式:<beanid="myBean"class="com.example.MyBean"lazy-init="true"/>
标签: spring java 后端

本文转载自: https://blog.csdn.net/qq_33129875/article/details/141191432
版权归原作者 java路飞 所有, 如有侵权,请联系我们删除。

“面试题-Spring Bean的生命周期”的评论:

还没有评论