
很多人觉得 Spring Bean 很简单ComponentpublicclassUserService{}项目启动AutowiredprivateUserServiceuserService;直接就能用了所以很多人的理解是Spring 帮我们干的事无非就是new UserService() 然后放进容器完事但真实情况远比想象复杂。一个 Bean 从出生到死亡会经历完整生命周期实例化↓属性注入↓初始化↓使用↓销毁Spring 很多核心能力AutowiredAOPTransactionalPostConstructBeanPostProcessor本质都依赖这套生命周期今天拆开看看1、Bean 为什么不能 new 完直接放进去很多人会问Spring 为什么不直接这样ObjectbeannewUserService();singletonObjects.put(beanName,bean);直接放进容器不就完了因为会立刻出现三个问题问题1依赖没注入ServiceclassUserService{AutowiredOrderServiceorderService;}此时orderServicenull调用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先创建对象UserServiceservicenewUserService();注意此时AutowiredprivateOrderServiceorderService;还是null因为这里只是创建对象还没有注入所以service只是个空壳还不能工作4、第二步属性填充源码populateBean()这里开始执行AutowiredValuesetter注入类似service.orderServicegetBean(OrderService.class);此时UserService↓OrderServiceBean 网络关系开始建立到这一步对象才真正组装完成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 几乎所有高级能力AutowiredAOPTransactionalPostConstruct本质都挂在生命周期扩展点上。所以理解生命周期不是在背实例化 → 注入 → 初始化…而是在理解Spring 到底如何管理、增强、控制一个对象的一生当你理解这一点再回头看doCreateBean()看到的就不是方法调用链而是 Spring 管理对象的完整过程关于老潘持续拆 Spring、MySQL、Redis 底层原理复盘真实线上问题。一起把“会用”变成“看懂”。如果有帮助点个赞、收藏支持一下。下一篇BeanPostProcessor 为什么这么重要Spring 几乎所有黑科技都靠它感兴趣可以关注避免刷着刷着找不到。