容器启动时到底做了什么?@Bean 方法是什么时候变成 Bean 的?BeanFactoryPostProcessor 和 BeanPostProcessor 在哪一步被创建?失败了会怎样?这篇把 refresh() 的每一步重写一遍加上计数和时间线,用 Spring Framework 7.0.9 逐步量出来。
prepareRefresh BeanDefinition 6→ 6 单例 0→ 0 115 µs obtainFreshBeanFactory BeanDefinition 6→ 6 单例 0→ 0 87 µs prepareBeanFactory BeanDefinition 6→ 6 单例 0→ 4 4081 µs postProcessBeanFactory BeanDefinition 6→ 6 单例 4→ 4 2 µs invokeBeanFactoryPostProcessors BeanDefinition 6→15 单例 4→ 9 76456 µs registerBeanPostProcessors BeanDefinition 15→15 单例 9→12 4683 µs initMessageSource BeanDefinition 15→15 单例 12→13 26916 µs initApplicationEventMulticaster BeanDefinition 15→15 单例 13→14 681 µs onRefresh BeanDefinition 15→15 单例 14→14 2 µs registerListeners BeanDefinition 15→15 单例 14→14 83 µs finishBeanFactoryInitialization BeanDefinition 15→15 单例 14→20 11373 µs finishRefresh BeanDefinition 15→15 单例 20→21 8001 µs refresh 之前的 BeanDefinition:[org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory, main.Conf] prepareBeanFactory 之后的单例:[environment, systemProperties, systemEnvironment, applicationStartup] refresh 之后新增的:[main.Conf, bfpp, bpp, a, b, proto, lazyOne, life, init, listener]
每一步前后的 BeanDefinition 数和单例数、耗时都记下来:定义在第 5 步涨,单例分批增加。
--- 事件时间线 invokeBeanFactoryPostProcessors 构造 Bfpp(BeanFactoryPostProcessor) invokeBeanFactoryPostProcessors Bfpp.postProcessBeanFactory:此时 BeanDefinition 共 15 个,单例 9 个 registerBeanPostProcessors 构造 Bpp(BeanPostProcessor) finishBeanFactoryInitialization Bpp 处理 main.Conf finishBeanFactoryInitialization 构造 A finishBeanFactoryInitialization Bpp 处理 a finishBeanFactoryInitialization 构造 B(依赖 A) finishBeanFactoryInitialization Bpp 处理 b finishBeanFactoryInitialization 构造 Life(SmartLifecycle) finishBeanFactoryInitialization Bpp 处理 life finishBeanFactoryInitialization 构造 Init finishBeanFactoryInitialization Bpp 处理 init finishBeanFactoryInitialization Bpp 处理 listener finishBeanFactoryInitialization SmartInitializingSingleton.afterSingletonsInstantiated() finishRefresh Life.start() finishRefresh ContextRefreshedEvent --- refresh 完成后:getBean(Proto) 两次、getBean(LazyOne) 一次 refresh 之后 构造 Proto(prototype) refresh 之后 Bpp 处理 proto refresh 之后 构造 Proto(prototype) refresh 之后 Bpp 处理 proto refresh 之后 构造 LazyOne(@Lazy) refresh 之后 Bpp 处理 lazyOne close() Life.stop() close() B.@PreDestroy close() A.@PreDestroy isActive/isRunning:isActive=false isRunning=false BeanFactoryPostProcessor 和 BeanPostProcessor 本身也是 Bean,而且要最早被创建(分别在 invokeBeanFactoryPostProcessors、registerBeanPostProcessors 里);普通单例都在 finishBeanFactoryInitialization 里按定义顺序创建,依赖会先于使用者创建;prototype 与 @Lazy 的 Bean 在 refresh 期间不创建;SmartLifecycle.start() 与 ContextRefreshedEvent 在 finishRefresh 里
BeanFactoryPostProcessor 与 BeanPostProcessor 最早创建;普通单例在 finishBeanFactoryInitialization 按依赖顺序创建;prototype 与 @Lazy 不在 refresh 里创建。
失败之前完成了 10 个步骤,最后完成的是 registerListeners(下一步 finishBeanFactoryInitialization 抛出了异常)
异常 UnsatisfiedDependencyException: Error creating bean with name 'needs' defined in demo.Main$Bad: Unsatisfied dependency expressed through method 'needs' parameter 0: No qualifying bean of type 'demo.Main$Missing' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
finishBeanFactoryInitialization 构造 A
finishBeanFactoryInitialization A.@PreDestroy
失败后 isActive=falserefresh 抛异常时,已经创建的单例会被销毁,上下文不再活跃。
第二次 refresh:IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
GenericApplicationContext 的第二次 refresh 直接抛 IllegalStateException。