SPRING SERIES - LỖI IM LẶNG
Thời Điểm Và Danh Sách BPP
LIFECYCLE - XANH = TẦNG PHÓNG TO
Đọc từ trái sang phải. Màu đậm dần nghĩa là gần cơ chế hơn. Dấu
* đánh dấu điểm bài viết khai thác.
Triệu chứng A - bean sinh sớm
@Value không inject - field giữ giá trị mặc định
Cùng một gốcBPP cần thiết chưa có mặt tại thời điểm object đi qua lifecycle.
Triệu chứng B - proxy sinh muộn
@Transactional trong @PostConstruct không mở transaction
Mức 1 - bản đồ đầy đủ
AbstractApplicationContext.refresh()
12 bước điều phối thật trong source
prepareRefresh()Bật trạng thái, kiểm tra property bắt buộcobtainFreshBeanFactory()Tạo hoặc làm mới BeanFactoryprepareBeanFactory()ThêmApplicationContextAwareProcessorthủ côngpostProcessBeanFactory()Hook cho lớp context coninvokeBeanFactoryPostProcessors()BFPP chạy khi List BPP còn chưa đầyregisterBeanPostProcessors()Tìm, sắp thứ tự, thêm các BPP còn lạiinitMessageSource()Khởi tạo message sourceinitApplicationEventMulticaster()Khởi tạo bộ phát eventonRefresh()Hook cho context chuyên biệtregisterListeners()Đăng ký listener beanfinishBeanFactoryInitialization()Tạo các singleton non-lazy còn lạifinishRefresh()Công bố context đã sẵn sàng
Mức 2 - zoom bước 5 và 6
List BPP đầy lên khi nào?
Không phải rỗng hoặc đầy, mà đầy dần theo thời gian
prepareBeanFactory()Tự thêmApplicationContextAwareProcessor- BFPP được tạo sớm
@Valuechưa có processor phụ trách EnvironmentAwarevẫn chạyProcessor ở bước 1 gọi callback nàyregisterBeanPostProcessors()AutowiredAnnotationBeanPostProcessorvà các BPP khác vào List- Bean tạo về sau đi qua ListHook property, init và proxy chạy đúng lượt
Ranh giới chính xác: EnvironmentAware không phải BPP. Nó là callback do ApplicationContextAwareProcessor gọi. Vì processor này được thêm thủ công ở bước 3 của refresh(), một BFPP sinh ở bước 5 vẫn nhận được Environment.
Mức 3 - zoom nơi List được dùng
Một bean đi qua 7 chặng
Đường singleton phổ biến, không có circular reference
- InstantiateConstructor tạo object trần
postProcessProperties()@Autowiredvà@Valueđược inject- Aware cơ bản
BeanNameAware,BeanClassLoaderAware,BeanFactoryAwaređược gọi trực tiếp - BPP before initialization
EnvironmentAware,@PostConstructchạy trên object chưa được AOP bọc afterPropertiesSet()Callback củaInitializingBean- Custom init methodVí dụ
@Bean(initMethod = "warmUp") - BPP after initializationAuto-proxy creator có thể trả về AOP proxy
Lối ra theo đúng lifecycle
- BFPP cần cấu hìnhImplement
EnvironmentAwarehoặc nhậnEnvironmentbằng API hạ tầng. - Logic cần proxyChạy sau khi context sẵn sàng, ví dụ
ApplicationRunner, và gọi qua proxy.
Khi KHÔNG được kết luận
- Thấy một field
@ValuenullChưa đủ để kết luận bean sinh sớm; còn có key sai, profile sai hoặc binding sai. - Thấy không có transaction trong initChưa đủ để kết luận chỉ do thời điểm; self-invocation cũng có thể bỏ qua proxy.