跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Java面试——Spring Bean的生命周期全过程

Spring Bean的生命周期从哪里开始? Bean的生命周期不是从
@Bean
方法返回那一刻算起,也不是从
new
实例化开始——而是从Spring容器调用
AbstractAutowireCapableBeanFactory#createBean()
真正介入时启动。这个方法内部会依次触发:实例化(通过构造器或工厂)、属性填充、Aware接口回调、初始化前置/后置处理器、
InitializingBean#afterPropertiesSet()
、自定义
init-method
、最后才是可用状态。 常见误区是认为
@PostConstruct
在
afterPropertiesSet()
之前执行——其实它属于“初始化回调”的一部分,且优先级高于
InitializingBean
和
init-method
,但晚于所有Aware接口。 关键顺序(简化): 构造函数调用(非单例Bean每次getBean都走这步)
BeanNameAware#setBeanName()
BeanFactoryAware#setBeanFactory()
ApplicationContextAware#setApplicationContext()
(如果实现了)
PostProcessor#postProcessBeforeInitialization()
@PostConstruct
标注的方法
InitializingBean#afterPropertiesSet()
init-method
指定的方法
PostProcessor#postProcessAfterInitialization()
为什么@Bean的initMethod不生效? 最常见原因是:你把
init-method
写在了
@Bean
注解里,但方法签名不对或没被Spring识别。
@Configuration public class AppConfig { @Bean(initMethod = "init") public MyService myService() { return new MyService(); } }
这要求
MyService
必须有无参
public void init()
方法。如果方法是
private
、带参数、返回值非
void
,或者类路径下存在多个同名方法(重载),Spring会静默忽略——不会报错,也不会执行。 另外注意:
initMethod
和
@PostConstruct
不能共存于同一方法;若同时存在,
@PostConstruct
优先,
initMethod
会被跳过。 验证方式:在方法里加
System.out.println("init triggered")
并启动应用,没输出就说明没触发。 立即学习 “ Java免费学习笔记(深入) ”; Eclipse导入Android或其他的JAVA项目的正确方法 WORD版 本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载 DisposableBean与destroy-method为何有时不执行? 销毁逻辑只在**容器关闭时**触发,且前提是Bean由Spring完全管理生命周期。以下情况会导致
destroy-method
或
DisposableBean#destroy()
完全不调用: 使用
new ClassPathXmlApplicationContext(...)
但没调用
close()
或
registerShutdownHook()
Web环境用
AnnotationConfigServletWebServerApplicationContext
,但没配置
ContextLoaderListener
或等价机制 Bean作用域为
prototype
:Spring不负责销毁,需手动清理资源 容器异常退出(如kill -9),JVM直接终止,钩子来不及运行 推荐写法:
@Configuration public class AppConfig { @Bean(destroyMethod = "cleanup") public ResourceManager resourceManager() { return new ResourceManager(); } }
对应类中必须有
public void cleanup()
;若方法不存在,Spring默认查找
close()
或
shutdown()
——但这是隐式行为,不建议依赖。 如何在生命周期中安全获取其他Bean? 不能在构造器里直接注入依赖Bean并立即使用,尤其当目标Bean尚未初始化完成时。典型错误:
public class A { private final B b; public A(B b) { this.b = b; b.doSomething(); // ❌ 可能NPE或逻辑错乱,B还没走完自己的init流程 } }
正确时机是: 在
@PostConstruct
中使用(此时所有依赖已注入,且本Bean初始化阶段刚开始) 在
afterPropertiesSet()
中使用(同上,但需实现接口) 在
postProcessAfterInitialization()
中使用(此时整个Bean已就绪) 如果必须在构造器里访问其他Bean,确保它们是
static
或底层无状态工具类;否则应重构为延迟加载(
ObjectProvider
或
@Lazy
)。 Spring Bean生命周期里最易被忽略的点:**初始化完成 ≠ 线程安全可用**。比如一个Bean在
init-method
里启了一个后台线程,该线程可能早于其他Bean初始化完毕就开始执行——这时候靠的是开发者的显式同步或启动顺序控制(
@DependsOn
),Spring本身不保证跨Bean的初始化时序。

相关文章