
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免费学习笔记(深入)”;
iOS多线程编程对于iOS开发初学者来说,总是会觉得很难理解和掌握,现在通过几个实例来更加系统全面的理解iOS多线程编程,希望对大家有所帮助。 有些程序是一条直线,起点到终点;有些程序是一个圆,不断循环,直到将它切断。直线的如简单的Hello World,运行打印完,它的生命周期便结束了,像昙花一现那样;圆如操作系统,一直运行直到你关机。 一个运行着的程序就是一个进程或者叫做一个任务,一个进程至少包含一个线程,线程就是程序的执行流。Mac和iOS中的程序启动,创建好一个进程的同时,一个线程便开始运行,
DisposableBean与destroy-method为何有时不执行?
销毁逻辑只在**容器关闭时**触发,且前提是Bean由Spring完全管理生命周期。以下情况会导致destroy-method或DisposableBean#destroy()完全不调用:
- 使用
new ClassPathXmlApplicationContext(...)但没调用close()或registerShutdownHook()
- Web环境用
AnnotationConfigServletWebServerApplicationContext,但没配置ContextLoaderListener或等价机制
- Bean作用域为
prototype:Spring不负责销毁,需手动清理资源
- 容器异常退出(如kill -9),JVM直接终止,钩子来不及运行
new ClassPathXmlApplicationContext(...)但没调用close()或registerShutdownHook()
AnnotationConfigServletWebServerApplicationContext,但没配置ContextLoaderListener或等价机制prototype:Spring不负责销毁,需手动清理资源推荐写法:
@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<b></b>或@Lazy)。
init-method里启了一个后台线程,该线程可能早于其他Bean初始化完毕就开始执行——这时候靠的是开发者的显式同步或启动顺序控制(@DependsOn),Spring本身不保证跨Bean的初始化时序。









