文章目录
Spring Bean 生命周期分为哪几个阶段
- 实例化:Spring 容器通过调用构造函数来创建 Bean 的实例。在这个阶段,Spring 还会根据配置文件或者注解来决定 Bean 的具体实现类。
- 填充属性:在 Bean 实例化之后,Spring 会将配置文件中定义的属性注入到 Bean 实例中。这些属性可以是简单的数据类型,也可以是其他 Bean 的引用,具体取决于 Bean 的定义和注解配置。
- 初始化:- @PostConstruct 注解的方法:如果 Bean 类中有使用 @PostConstruct 注解的方法,Spring 会在填充属性之后调用这些方法。这个阶段通常用于 Bean 的初始化逻辑。- InitializingBean 接口:如果 Bean 实现了 InitializingBean 接口,Spring 会调用 afterPropertiesSet() 方法来进行初始化。- init-method 配置:在 XML 配置中,如果定义了 init-method,Spring 会在填充属性之后调用指定的方法进行初始化。
- 使用:在 Bean 完成初始化之后,Spring 容器就可以将其交给应用程序使用了。这个阶段是 Bean 的正常工作阶段。
- 销毁:- @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 方法负责。这个方法会在 DefaultListableBeanFactory 的 createBean 方法中被调用。
在这个方法中,首先检查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 接口,并重写 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法。以下是如何在项目中使用它的步骤:
- 创建自定义的 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}
- 将自定义 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 的生命周期?
- Singleton(单例)****描述: 默认作用域。Spring容器中只创建一个Bean实例,并在整个容器中共享这个实例。生命周期: 从容器启动到容器关闭期间,Bean实例始终存在。
- Prototype(原型)****描述: 每次请求都会创建一个新的Bean实例。每个实例都有独立的生命周期。生命周期: 每次获取Bean时,都会创建一个新的实例。Bean的生命周期从创建开始,到被垃圾回收时结束。
- Request(请求)****描述: 每个HTTP请求都会创建一个新的Bean实例。Bean的生命周期与HTTP请求相对应。生命周期: 从每个HTTP请求开始到请求结束,每次请求都会创建一个新的Bean实例。
- Session(会话)****描述: 每个HTTP会话创建一个新的Bean实例。Bean的生命周期与HTTP会话相对应。生命周期: 从每个HTTP会话开始到会话结束,每个会话都有一个独立的Bean实例。
- GlobalSession(全局会话)****描述: 在Portlet环境中使用。每个全局会话创建一个新的Bean实例。生命周期: 适用于Portlet应用中的全局会话,每个全局会话有一个独立的Bean实例。
例如,配置一个原型作用域的 Bean:
<beanid="myBean"class="com.example.MyBean"scope="prototype"/>
或通过注解@scope 设置
此外,我们还可以自定义 Bean 的初始化和销毁方法,以在 Bean 作用域开始和结束时执行特定逻辑。可以通过 init-method 和 destroy-method 属性来指定这些方法:
<beanid="myBean"class="com.example.MyBean"scope="prototype"init-method="start"destroy-method="end"></bean>
Spring中的延迟初始化是什么,如何配置延迟初始化?
在Spring中,延迟初始化(Lazy Initialization)是一种延迟Bean创建的机制,即只有在实际需要Bean时才会创建它,而不是在容器启动时就立即创建。这可以提高应用程序的启动速度和资源利用率,特别是对于那些不常用的Bean。
延迟初始化的配置方式
- 通过 @Lazy 注解- 应用场景:在类级别或方法级别使用,表示当Bean首次被使用时才会被创建。- 配置方式: - 在类上:对整个Bean类应用延迟初始化。
@Lazy@ComponentpublicclassMyBean{// Bean实现}
- 在方法上:对特定的Bean方法应用延迟初始化。@ConfigurationpublicclassAppConfig{@Bean@LazypublicMyBeanmyBean(){returnnewMyBean();}}
- 在 XML 配置中- 应用场景:在传统的XML配置中配置延迟初始化。- 配置方式:
<beanid="myBean"class="com.example.MyBean"lazy-init="true"/>
版权归原作者 java路飞 所有, 如有侵权,请联系我们删除。