Spring生命周期是Java后端面试的经典考题。能不能说明白扩展点(BeanPostProcessor、Aware接口)——是真正能扩展Spring还是只会用@Autowired,这道题就能看出来。
实例化:Spring调用构造方法(或@Bean工厂方法)创建原始对象。
属性填充:解析依赖并注入,@Autowired、@Value、@Resource在这一步被处理。
Aware回调:Bean实现了BeanNameAware、BeanFactoryAware、ApplicationContextAware等接口的话,Spring调对应setter把框架上下文塞进去。
BeanPostProcessor.postProcessBeforeInitialization在每个Bean上都跑;然后进入初始化——@PostConstruct、InitializingBean.afterPropertiesSet()、BeanDefinition里配的init-method。
BeanPostProcessor.postProcessAfterInitialization——关键:AOP代理就是在这一步由AnnotationAwareAspectJAutoProxyCreator生成的。到这里Bean才真正就绪。
关闭时销毁:@PreDestroy、DisposableBean.destroy()、自定义destroy-method。
Spring Bean生命周期主要分六个阶段。第一步实例化——Spring调构造方法或@Bean工厂方法创建原始对象。第二步属性填充——解析依赖并注入;@Autowired、@Value、@Resource都在这一步,具体由AutowiredAnnotationBeanPostProcessor处理。第三步Aware回调——Bean实现了BeanNameAware、BeanFactoryAware、ApplicationContextAware、EnvironmentAware等接口,Spring调对应setter把框架内部的引用塞给Bean。第四步是BeanPostProcessor.postProcessBeforeInitialization,每个Bean都会被所有注册的BeanPostProcessor经过一遍,这是框架的拦截入口。之后进入初始化:@PostConstruct最先执行、然后InitializingBean.afterPropertiesSet()、最后BeanDefinition里配的init-method。第五步BeanPostProcessor.postProcessAfterInitialization——这一步最关键,AOP代理就是在这里包上去的。AnnotationAwareAspectJAutoProxyCreator本身就是个BeanPostProcessor,它在post-init时扫描Bean是否命中切点,命中就用CGLIB或JDK动态代理包一层,返回代理对象给容器。从此刻起,ApplicationContext持有的就是代理,所有@Autowired注入进来的也都是代理。第六步销毁——容器关闭时先@PreDestroy,然后DisposableBean.destroy(),最后destroy-method。一个非常重要的推论:AOP代理是在post-init阶段生成的,所以同类里方法A调方法B(this.methodB()),调用的是原对象不是代理,@Transactional这类注解会失效——这就是面试官最爱追问的"自调用失效"问题。解法是通过AopContext.currentProxy()拿代理,或者把自己注入自己。
讲AOP那一步一定要带出"同类自调用事务失效"这个经典追问。
初始化三种回调的顺序要记牢:@PostConstruct → InitializingBean → init-method。
能叫出具体BeanPostProcessor名字(AnnotationAwareAspectJAutoProxyCreator)是深度信号。
临场忘了初始化顺序,即答侠可以立即提示完整序列。
setter/字段注入的循环用三级缓存解决——属性填充阶段可以从二级缓存拿到正在初始化Bean的早期引用。构造方法循环无法解决,会直接抛异常。
BeanFactory是最小IoC容器;ApplicationContext加了预初始化、事件、国际化、资源加载,是超集。业务代码一般用ApplicationContext。
prototype只会走到init回调,销毁由调用方负责——容器不追踪prototype的生命周期。