Part 03 · Spring Framework & Spring Boot · 3.2
Câu hỏi Spring và Spring Boot
Trả lời theo mechanism → proxy/runtime boundary → trade-off → failure mode → example. Không học thuộc annotation mà không giải thích call path.
1. Container và proxy
1. IoC và DI giải quyết vấn đề gì?
Container sở hữu construction, wiring và lifecycle; application phụ thuộc abstraction. Constructor injection làm dependency bắt buộc và testable. DI không tự tạo architecture tốt nếu boundary sai.
2. Singleton bean có thread-safe không?
Không mặc định. Singleton chỉ là một instance trong context; mutable request state bị nhiều threads truy cập. Service nên stateless hoặc đồng bộ và sở hữu state đúng.
3. BeanPostProcessor dùng làm gì?
Can thiệp trước/sau initialization và có thể trả proxy. AOP, transaction cùng nhiều infrastructure features dựa vào cơ chế này.
4. Vì sao self-invocation làm @Transactional mất hiệu lực?
Call qua
this không đi qua proxy nên interceptor không chạy. Đặt boundary ở collaborator/use case khác hoặc gọi qua proxy entry point.5. JDK proxy khác class proxy?
JDK proxy implement interface; class proxy subclass target. Final/private method không thể được override/intercept như method thường. Cả hai cùng có giới hạn self-invocation.
2. Boot và web
6. Spring Boot thêm gì cho Spring?
Opinionated dependency management, auto-configuration, starters, executable packaging, external config và production features. Nó không thay IoC container cốt lõi.
7. Auto-configuration hoạt động và back off thế nào?
Configuration classes có conditions theo classpath, bean, property và application type. Khi user cung cấp bean phù hợp, auto-config thường back off. Dùng condition report để debug.
8. Filter khác interceptor?
Filter ở Servlet chain trước DispatcherServlet, phù hợp security, encoding và request wrapping. Interceptor ở MVC handler lifecycle, biết handler nhưng không thay filter cho servlet boundary.
9. Mô tả Spring MVC request lifecycle
Filter → DispatcherServlet → HandlerMapping → HandlerAdapter → argument resolution/validation → controller → return handling/message conversion → response; exception qua resolver hoặc advice.
10. @ConfigurationProperties tốt hơn @Value khi nào?
Khi config có cấu trúc, cần binding type-safe, validation và metadata.
@Value hợp giá trị nhỏ; dùng rải rác làm khó quản lý và test.3. Modules, starters và dependency management
11. Spring Framework module khác Boot starter?
Module chứa API/runtime capability như context, transaction hay MVC. Starter chủ yếu là dependency descriptor gom libraries; nó có thể kéo modules và auto-config nhưng không phải chính capability hoặc IoC container.
12. Spring Boot Starter là gì? Bạn từng dùng starter nào?
Starter gom dependency set có opinion cho use case: web, data-jpa, security, actuator hoặc test. Câu trả lời tốt nêu use case và trade-off, không chỉ đọc danh sách.
13. Starter khác BOM/dependency management?
Starter chọn nhóm artifacts; BOM/dependency management căn versions tương thích. Parent/plugin còn cung cấp build defaults và executable packaging. Import BOM không tự kéo dependencies hoặc toàn bộ plugin config.
14. Thêm starter có tự động tạo mọi bean không?
Không. Starter đưa classes/auto-config lên classpath; conditions vẫn kiểm class, bean, property và application type. Thiếu driver/property hoặc có user bean thì configuration có thể không match hoặc back off.
15. Loại Tomcat khỏi starter-web để dùng Jetty thế nào?
Exclude
spring-boot-starter-tomcat, thêm starter Jetty, rồi kiểm dependency tree, server-specific config, tests và operations. Exclude dependency không bảo đảm mọi auto-config khác tương thích.16. Custom starter nên được thiết kế thế nào?
Tách autoconfigure module và starter descriptor; dùng
@AutoConfiguration, typed properties, conditional beans, back-off và AutoConfiguration.imports; test bằng ApplicationContextRunner. Không scan consumer packages hay tạo side effect bất ngờ.4. Transaction và data
17. REQUIRED khác REQUIRES_NEW?
REQUIRED tham gia transaction hiện tại; REQUIRES_NEW suspend outer và mở transaction/connection mới. Lạm dụng có thể cạn pool và tạo consistency khó hiểu.
18. Checked exception có rollback mặc định không?
Declarative rule mặc định rollback RuntimeException/Error, không phải mọi checked exception. Thiết kế exception và
rollbackFor có chủ đích.19. Vì sao không nên gọi remote API trong DB transaction dài?
Nó giữ connection/lock khi chờ network, tăng contention và failure coupling. Tách transaction; dùng state machine, Outbox và idempotency theo consistency requirement.
20. N+1 là gì và sửa ra sao?
Một query load parents rồi N queries load associations. Dùng fetch join, entity graph, projection hoặc batching theo use case; không bật EAGER toàn cục.
21. save() có luôn chạy INSERT ngay?
Không. Persistence context và flush mode quyết định SQL timing; ID strategy có thể buộc insert sớm nhưng vẫn không đồng nghĩa commit.
5. Security và operations
22. SecurityFilterChain là gì?
Chuỗi security filters được FilterChainProxy chọn theo request matcher để xử lý authentication, context, authorization và protocol protections.
23. CORS khác CSRF?
CORS là browser policy về cross-origin response access. CSRF lợi dụng credential tự gửi để thực hiện request ngoài ý muốn. Cấu hình một cái không tự giải quyết cái kia.
24. @Async có rủi ro gì?
Proxy/self-invocation, executor unbounded, mất context, exception khó thấy, shutdown và cancellation. Cần bounded executor, rejection và observability.
25. Liveness và readiness khác nhau?
Liveness trả lời process có cần restart; readiness trả lời có nhận traffic được không. Đưa DB ngoài vào liveness có thể tạo restart cascade.
26. Chẩn đoán startup failure thế nào?
Đọc root cause, bean candidates, config binding và condition report; kiểm component scan, profiles và dependency versions. Không thêm annotation ngẫu nhiên.
6. Câu hỏi chuyên sâu
27. BeanFactoryPostProcessor khác BeanPostProcessor?
Loại đầu sửa bean definitions trước instantiate; loại sau xử lý instances và có thể trả proxy. Dùng sai phase có thể tạo bean quá sớm và bỏ qua post-processing.
28. Prototype bean destruction được quản lý thế nào?
Container tạo và configure nhưng không theo dõi destruction đầy đủ như singleton; client hoặc custom scope phải cleanup resource.
29. UnexpectedRollbackException xuất hiện vì sao?
Inner logical REQUIRED scope đánh physical transaction rollback-only, outer bắt lỗi rồi vẫn cố commit; manager báo commit không thể xảy ra.
30. Advice order ảnh hưởng retry và transaction thế nào?
Retry ngoài transaction tạo transaction mới mỗi attempt; retry trong có thể lặp trên transaction rollback-only. Order phải theo desired failure semantics.
31. Context cache của Spring Test gây vấn đề gì?
Reuse context tăng tốc, nhưng mutable singleton/test config có thể rò state; quá nhiều unique contexts hoặc
@DirtiesContext làm suite chậm.32. OSIV có trade-off gì?
Cho lazy load qua web layer nhưng che query/N+1, kéo persistence context và làm transaction/data-access boundary mơ hồ.
33. SecurityContext qua async thread ra sao?
ThreadLocal không tự truyền vào executor. Dùng delegating executor/context propagation có cleanup hoặc truyền principal data rõ; không để context rò giữa tasks.
34. @Cacheable có chống stampede không?
Không mặc định trên distributed nodes. Provider hoặc sync option chỉ có semantics giới hạn; cần single-flight, lock, refresh strategy và TTL phù hợp.
35. Khi nào chọn MVC + virtual threads thay WebFlux?
Khi ecosystem chủ yếu blocking và muốn code imperative, virtual threads có migration cost thấp hơn. WebFlux hợp end-to-end reactive, streaming và backpressure nhưng không được block.
36. Debug pool saturation theo thứ tự nào?
Đo request threads, DB connections, executor queues, HTTP client pool và downstream latency cùng timeline; tìm queue đầu tiên tích tụ thay vì tăng mọi pool.
7. Câu hỏi nền tảng bổ sung
37. Spring inject List và Map các bean như thế nào?
List<PaymentHandler> nhận mọi bean tương thích và có thể sắp bằng @Order/Ordered. Map<String, PaymentHandler> dùng bean name làm key. Generic type chọn candidates; dùng qualifier khi cần thu hẹp và tránh để bean mới vô tình đổi business flow.38. @Transactional hoạt động thế nào, nên đặt ở đâu?
Proxy/interceptor dùng transaction manager mở hoặc tham gia transaction, bind resource vào execution context rồi commit/rollback. Đặt ở public application use case bao trùm invariant, giữ ngắn. Self-invocation, private/final method, object tự tạo, async hoặc reactive flow có boundary khác.
39. Bean lifecycle và @PostConstruct, @PreDestroy diễn ra ra sao?
Instantiate → inject → Aware → post-processor before-init → init callbacks → after-init/proxy → ready; khi context đóng chạy destroy callbacks. Object ngoài container không có callback; prototype không được quản lý destruction đầy đủ.
8. Follow-up theo tình huống
40. Dùng List/Map injection cho Strategy pattern thế nào?
Mỗi strategy là bean. Business key không nên phụ thuộc ngầm vào bean name; mỗi strategy nên công bố enum/key, registry immutable validate duplicate lúc startup. Với List, order phải explicit và được test khi thêm strategy.
41. @Primary và @Qualifier ảnh hưởng collection injection ra sao?
@Primary chủ yếu giải ambiguity cho một bean đơn; List/Map vẫn nhận candidates phù hợp. Qualifier lọc tập bean; Order điều khiển List; Map dùng bean name làm key.42. Bắt exception bên trong @Transactional có rollback không?
Nếu exception không thoát interceptor, transaction thường commit trừ khi rollback-only. Inner REQUIRED có thể đã đánh rollback-only và làm outer commit ném
UnexpectedRollbackException. Recovery phải ở boundary rõ.43. readOnly, isolation và timeout có phải guarantee tuyệt đối?
readOnly thường là hint, không phải authorization. Isolation có thể bị bỏ qua khi join transaction hiện có hoặc resource không hỗ trợ. Timeout phụ thuộc manager/driver; test bằng DB thật và đặt request/network deadline riêng.44. Vì sao transaction không tự truyền sang @Async?
Imperative transaction context thường gắn thread hiện tại. Worker mở transaction riêng; truyền command/data rõ và dùng Outbox hoặc event after commit cho durable handoff.
45. Vì sao @Transactional/@Async trên @PostConstruct thường sai?
PostConstruct chạy trong initialization trước khi proxy hoàn chỉnh được dùng như entry point. Tách startup work sang bean khác, runner/event phù hợp hoặc lifecycle component có readiness và error policy.
46. @PreDestroy có đủ cho graceful shutdown?
Chỉ phù hợp cleanup ngắn khi context đóng có trật tự; crash, SIGKILL hoặc timeout không bảo đảm callback. Service phải stop traffic, not-ready, drain work và dừng producer/consumer theo order; SmartLifecycle hỗ trợ phase.
Nguồn ôn tập bổ sung: ITviec · Top 45+ câu hỏi Spring Boot. Dùng như checklist, sau đó đối chiếu Spring official docs theo version.
Lưu ý version: tài liệu cũ có thể đăng ký auto-configuration bằng
spring.factories. Spring Boot hiện đại dùng META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.