Bean 为什么需要生命周期?90%的人只会背流程
很多人觉得 Spring Bean 很简单:
@ComponentpublicclassUserService{}项目启动:
@AutowiredprivateUserServiceuserService;直接就能用了
所以很多人的理解是:
Spring 帮我们干的事,无非就是:new UserService() 然后放进容器完事,但真实情况远比想象复杂。
一个 Bean 从出生到死亡,会经历完整生命周期:
实例化
↓
属性注入
↓
初始化
↓
使用
↓
销毁
Spring 很多核心能力:
@Autowired
AOP
@Transactional
@PostConstruct
BeanPostProcessor
本质都依赖这套生命周期,今天拆开看看:
1、Bean 为什么不能 new 完直接放进去?
很多人会问:Spring 为什么不直接这样:
Objectbean=newUserService();singletonObjects.put(beanName,bean);直接放进容器不就完了?因为会立刻出现三个问题
问题1:依赖没注入
@ServiceclassUserService{@AutowiredOrderServiceorderService;}此时:
orderService=null,调用:orderService.create(); 直接:NullPointerException
因为对象创建了,但对象关系没建立
问题2:事务直接失效
例如:
@Transactionalpublicvoidsave(){}很多人以为事务加个注解就生效,实际上事务依赖:Proxy(UserService)
而不是:new UserService(),Spring需要偷偷换成代理对象:
UserService
↓
Proxy(UserService)
否则:事务、AOP全部失效
问题3:初始化逻辑没人执行
例如:
@PostConstructpublicvoidinit(){System.out.println("初始化");}如果:new UserService() 结束,谁调用:init()
没人。所以 Spring 必须给 Bean 一个完整生命周期
本质一句话:Spring 需要在对象不同阶段插入逻辑
2、Bean 生命周期源码入口在哪?
核心类:
AbstractAutowireCapableBeanFactory入口:
createBean()继续往下:
doCreateBean()这里几乎就是整个生命周期总控
源码主线:
createBeanInstance()
实例化
↓
populateBean()
属性填充
↓
initializeBean()
初始化
↓
registerDisposableBeanIfNecessary()
注册销毁
有没有发现:前面的生命周期图,本质就是源码执行顺序
所以生命周期不是背流程,而是在读 Spring 创建对象过程
3、第一步:实例化
Spring先创建对象:
UserServiceservice=newUserService();注意:此时:
@AutowiredprivateOrderServiceorderService;还是:null,因为这里只是创建对象,还没有注入
所以:service,只是个空壳,还不能工作
4、第二步:属性填充
源码:
populateBean()
这里开始执行:
@Autowired
@Value
setter注入
类似:
service.orderService=getBean(OrderService.class);此时:
UserService
↓
OrderService
Bean 网络关系开始建立
到这一步:对象才真正组装完成
5、第三步:Aware 回调
如果 Bean 实现:
@ComponentpublicclassUserServiceimplementsBeanNameAware{@OverridepublicvoidsetBeanName(Stringname){System.out.println(name);}}Spring 会主动回调:setBeanName()
把容器信息传进来,类似还有:
BeanNameAwareBeanFactoryAwareApplicationContextAware很多框架都在这里拿容器
本质:不是你找 Spring,而是 Spring 主动把自己给你
6、第四步:BeanPostProcessor 登场
源码:
applyBeanPostProcessorsBeforeInitialization()↓
初始化
↓
applyBeanPostProcessorsAfterInitialization()这里是 Spring 最强扩展点之一
很多核心功能都藏在这里:
AOP
事务
缓存
异步
尤其:postProcessAfterInitialization()
这里可能返回:不是原对象,而是:Proxy(UserService)
很多人调试:
System.out.println(userService.getClass());输出:classcom.demo.UserService$$SpringCGLIB$$0第一次看到很多人会懵:我写的不是:new UserService() 吗?
为什么变成:“UserService$SpringCGLIBSpringCGLIBSpringCGLIB-0”
原因就在这里,Spring 在生命周期后置阶段:偷偷把对象换了
userService.getClass()输出:
7、第五步:初始化
这里可能执行:@PostConstruct
或者:afterPropertiesSet()
或者:init-method
例如:
@PostConstructpublicvoidinit(){System.out.println("初始化");}有人会问:为什么不用构造函数?
因为构造函数执行时:对象虽然创建了,但依赖还没注入
而:@PostConstruct 执行时:对象创建完成,依赖注入完成
终于可以开始真正准备工作。
例如:
初始化连接池
加载配置
预热缓存
8、第六步:销毁
容器关闭:context.close();
触发:@PreDestroy
或者:DisposableBean
例如:
@PreDestroypublicvoiddestroy(){executor.shutdown();}很多线上问题都出在这里:
线程池没关闭,MQ连接没释放,数据库连接没回收
服务重启几次后:资源直接耗尽,所以 Spring 会统一回收资源
总结
很多人背 Bean 生命周期:
实例化
↓
属性注入
↓
初始化
↓
使用
↓
销毁
但真正应该记住的不是流程。
而是:
创建对象
↓
组装对象
↓
增强对象
↓
使用对象
↓
销毁对象
因为 Spring 真正做的事情,从来不是:new UserService()
而是:接管对象从出生到死亡的整个过程
Spring 几乎所有高级能力:
@Autowired
AOP
@Transactional
@PostConstruct
本质都挂在生命周期扩展点上。
所以理解生命周期,不是在背:实例化 → 注入 → 初始化…
而是在理解:Spring 到底如何管理、增强、控制一个对象的一生
当你理解这一点,再回头看:doCreateBean()
看到的就不是方法调用链,而是 Spring 管理对象的完整过程
关于老潘:
持续拆 Spring、MySQL、Redis 底层原理,复盘真实线上问题。
一起把“会用”变成“看懂”。
如果有帮助,点个赞、收藏支持一下。
下一篇:BeanPostProcessor 为什么这么重要?Spring 几乎所有黑科技都靠它
感兴趣可以关注,避免刷着刷着找不到。
