作者简介:王哥,CSDN2022博客总榜Top100、博客专家
技术交流:定期更新Java硬核干货,不定期送书活动
王哥多年工作总结:Java学习路线总结, 点击 突击面试
数十万人的面试选择: 面试说人话系列《面试1v1》
我是 javapub,一名 Markdown
程序员从,八股文种子选手。
面试官: 小伙子,听说你对 Spring Bean 生命周期比较熟悉,我们聊聊吧。Spring Bean 都有哪些生命周期阶段?
候选人: Spring Bean 的生命周期可以分为 5 个阶段:
面试官: 聪明!初始化方法有哪些?在源码层面,Spring 是如何调用这些方法的?
候选人: Spring Bean 提供了 3 种初始化方法:
在源码层面,这些方法的调用是在 AbstractAutowireCapableBeanFactory
的 initializeBean
方法中实现的:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// ...
// 1. 处理 PostConstruct 注解
if (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet")) {
// 2. 实现了 InitializingBean 接口的 Bean 会调用 afterPropertiesSet() 方法
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
}
// 3. 调用自定义的 init-method
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(bean instanceof InitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
Method initMethod = bean.getClass().getMethod(initMethodName);
initMethod.invoke(bean);
}
}
}
面试官: 不错,你对 Spring Bean 的初始化过程很清楚!那销毁方法哪些?原理又是什么?
候选人: Spring Bean 提供了 2 种销毁方法:
在源码层面,这些方法的调用是在 AbstractAutowireCapableBeanFactory
的 destroyBean
方法中实现的:
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// 1. 实现了 DisposableBean 接口的 Bean 会调用 destroy() 方法
if (bean != null) {
bean.destroy();
}
// 2. 调用自定义的 destroy-method
String destroyMethodName = getDestroyMethodName(beanName);
if (destroyMethodName != null) {
Method destroyMethod = null;
try {
// 获取 destroy-method 方法对象
destroyMethod = bean.getClass().getMethod(destroyMethodName);
} catch (NoSuchMethodException ex) {
throw new BeanDefinitionStoreException(...);
}
// 调用方法
try {
if (destroyMethod != null) {
destroyMethod.invoke(bean);
}
} catch (...) {
throw new BeanCreationException(...);
}
}
}
面试官: 棒!最后,Spring Bean 的作用域都有哪些?如何控制 Bean 的生命周期?
候选人: Spring Bean 的作用域有 5 种:
我们可以通过 scope
属性控制 Bean 的作用域,从而影响其生命周期:
<bean id="..." class="..." scope="prototype"/>
此外,我们还可以自定义 Bean 的初始化和销毁方法,在 Bean 作用域开始和结束时触发:
<bean id="..." class="..." scope="prototype"
init-method="start" destroy-method="end">
bean>
这样我们就可以在 start()
方法中执行初始化逻辑,在 end()
方法中执行清理工作,从而精确控制 Bean 的生命周期。
面试官: 很全面,佩服佩服!如果再给你一个机会,你觉得还可以在哪些方面加深对 Spring Bean 生命周期的理解?
候选人: 这里有几个方面可以进一步加深对 Spring Bean 生命周期的理解:
lazy-init
属性设置。depends-on
属性配置。面试官: 非常棒,这些点精彩极了!你的回答已经很全面和深入,对 Spring Bean 生命周期有清晰理解,这些又是常见的面试重点,我相信面试一定会取得很好的表现,加油!我们就聊到这里,很高兴与你的交流,谢谢!
最近我在更新《面试1v1》系列文章,主要以场景化的方式,讲解我们在面试中遇到的问题,致力于让每一位工程师拿到自己心仪的offer,感兴趣可以关注JavaPub追更!
目录合集:
Gitee:https://gitee.com/rodert/JavaPub
GitHub:https://github.com/Rodert/JavaPub
http://javapub.net.cn