Spring Core & Boot
2/41
Bài 2 / 41~12 phútNhập môn & IoC/DILộ trình · chặng 13/21Miễn phí… lượt xem

Spring Là Gì: Bài Toán Framework Giải Quyết Và Bản Đồ Cốt Lõi

Lịch sử Spring từ nỗi đau EJB 2.x, bản chất IoC container, cấu trúc 5 lớp Spring Boot và vòng đời của một HTTP request trong kiến trúc enterprise.

TL;DR: Spring ra đời giai đoạn 2003-2004 nhằm giải quyết sự cồng kềnh, phân tán và khó kiểm thử của Java EE/EJB 2.x. Trọng tâm của framework là giải phóng lập trình viên khỏi việc tự khởi tạo và liên kết các đối tượng bằng toán tử new gây tight coupling, thay bằng cơ chế Inversion of Control (IoC). Spring Boot không phải là một framework thay thế hoàn toàn mới mà là bộ công cụ đóng gói thông minh gồm 5 thành phần: Spring Framework, Starter dependencies, Auto-configuration, Embedded server và Actuator.

Khi mở bất kỳ dự án Java backend quy mô doanh nghiệp nào, bạn đều sẽ bắt gặp tiền tố org.springframework.*. Framework này hiện diện trong phần lớn yêu cầu tuyển dụng kỹ sư Java. Tại sao một nền tảng khởi nguồn từ năm 2003 vẫn giữ vững vị thế áp đảo trong kỷ nguyên microservices hiện nay? Câu trả lời nằm ở tư duy kiến trúc và bài toán đảo ngược quyền điều khiển mà Spring đã giải quyết triệt để.

Vì sao Spring ra đời từ sự thất bại của Java EE và EJB 2.x?

Đầu thập niên 2000, thế giới Java doanh nghiệp chịu sự chi phối của chuẩn Java EE (sau này là Jakarta EE) cùng công nghệ EJB 2.x (Enterprise JavaBeans), chạy trên các Application Server cồng kềnh như BEA WebLogic, IBM WebSphere hay JBoss.

Để hiện thực hóa một logic nghiệp vụ đơn giản như lưu đơn mượn sách (BookingService), nhà phát triển buộc phải tạo tối thiểu 5 thành phần:

  1. Remote Interface (BookingServiceRemote extends EJBObject): Định nghĩa các hàm gọi từ xa qua giao thức RMI.
  2. Home Interface (BookingServiceHome extends EJBHome): Định nghĩa hàm vòng đời tạo bean create().
  3. Bean Class (BookingServiceBean implements SessionBean): Cài đặt hàng loạt callback nặng nề (ejbCreate, ejbActivate, ejbPassivate, ejbRemove).
  4. Deployment Descriptor chuẩn (ejb-jar.xml): File cấu hình XML dài hàng chục dòng để khai báo bean với container.
  5. Vendor Deployment Descriptor (weblogic-ejb-jar.xml): File cấu hình XML đặc thù riêng cho từng hãng máy chủ để ánh xạ tên JNDI.

Hậu quả là 70% mã nguồn dự án chỉ phục vụ cho hạ tầng kỹ thuật (plumbing code) thay vì giải quyết bài toán kinh doanh.

Đối chiếu khối lượng phải viết để có một BookingService: cột EJB gồm interface home, interface remote, bean class kèm năm callback, file ejb-jar.xml và file descriptor riêng của vendor; cột Spring chỉ có một class POJO không kế thừa gì của framework

Bốn rào cản chí mạng khiến EJB 2.x sụp đổ:

Vấn đềTác động thực tế
Vendor lock-inĐổi server đòi hỏi viết lại toàn bộ file XML descriptor và xử lý lỗi không tương thích
Không thể test offlineChạy 1 unit test buộc phải khởi động WebLogic mất vài phút mỗi lần
Boilerplate khổng lồTốn trung bình 5 file và hàng trăm dòng cấu hình cho mỗi method nghiệp vụ
Vòng đời phức tạpCallback kích hoạt và giải phóng bộ nhớ nhập nhằng, cực kỳ khó truy vết lỗi

Năm 2002, Rod Johnson xuất bản cuốn sách kinh điển "Expert One-on-One J2EE Design and Development". Ông giới thiệu framework thử nghiệm Interface21, chứng minh rằng lập trình với POJO (Plain Old Java Object) kết hợp container tiêm phụ thuộc gọn hơn gấp 10 lần và kiểm thử offline hoàn hảo. Tháng 3 năm 2004, phiên bản Spring 1.0 chính thức phát hành, mở ra "mùa xuân ấm áp sau mùa đông băng giá của J2EE".

Bài toán cốt lõi về quyền điều khiển đối tượng được giải quyết ra sao?

Hãy xem xét một đoạn mã Java kinh điển khi chưa áp dụng framework quản lý phụ thuộc:

Java
public class OrderService {
    private PaymentGateway payment = new StripePayment();
    private EmailService email = new SmtpEmailService();
    private InventoryClient inventory = new HttpInventoryClient("http://inv:8080");

    public void placeOrder(Order order) {
        inventory.reserve(order.items());
        payment.charge(order.total());
        email.send(order.customer(), "Order confirmed");
    }
}

Dù đoạn mã này biên dịch và chạy được, nó tiềm ẩn các lỗi kiến trúc nghiêm trọng:

  • Khớp nối chặt (Tight Coupling): OrderService gắn cứng với cài đặt cụ thể StripePayment. Việc chuyển đổi sang cổng thanh toán khác buộc lập trình viên phải sửa đổi mã nguồn service.
  • Bất khả thi trong Unit Test: Phương thức placeOrder không thể kiểm thử cô lập mà luôn kích hoạt gọi HTTP ra Stripe thật và SMTP thật.
  • Rò rỉ cấu hình: Địa chỉ mạng http://inv:8080 bị gắn cứng, đòi hỏi biên dịch lại mã nguồn khi chuyển giữa các môi trường kiểm thử và sản xuất.
  • Trách nhiệm vòng đời bị phân tán: Không có quy chuẩn dọn dẹp kết nối mạng hay hủy đối tượng khi ứng dụng tắt.

Spring giải quyết vấn đề này bằng việc đưa vào IoC Container:

  1. Đối tượng không tự khởi tạo phụ thuộc mà chỉ khai báo các hợp đồng (Interface).
  2. Quyền tạo mới, quản lý vòng đời và liên kết (wiring) các đối tượng được chuyển giao hoàn toàn cho Container bên ngoài.

Spring Framework tổ chức các module kiến trúc như thế nào?

Spring Framework không phải là một file jar đơn khối khổng lồ, mà là tập hợp khoảng 20 module chuyên biệt. Tất cả các tính năng cao cấp đều vận hành trên nền tảng của Core Container:

Bốn nhóm module Data Access, Web, AOP và Testing đều có mũi tên đổ xuống Core Container gồm spring-beans và spring-context, cho thấy không nhóm nào đứng độc lập với container

Các nhóm module then chốt trong hệ sinh thái:

  • Core Container (spring-beans, spring-context): Cung cấp BeanFactory và ApplicationContext, quản lý vòng đời bean và giải quyết đồ thị phụ thuộc.
  • Data Access (spring-jdbc, spring-orm, spring-tx): Chuẩn hóa việc truy cập cơ sở dữ liệu, quản lý giao dịch declarative qua @Transactional và tích hợp Hibernate/JPA.
  • Web Stack (spring-web, spring-webmvc, spring-webflux): Hỗ trợ xây dựng REST API và Web MVC theo mô hình Servlet blocking truyền thống hoặc Reactive non-blocking Streams.
  • AOP (spring-aop): Cung cấp cơ chế lập trình hướng khía cạnh để tách biệt các mối quan tâm xuyên suốt (logging, bảo mật, quản lý giao dịch).
  • Test (spring-test): Hỗ trợ kiểm thử tích hợp, nạp context và mock servlet environment.

Spring Boot đóng gói 5 thành phần cốt lõi nào cho ứng dụng?

Trước năm 2014, việc khởi tạo một ứng dụng Spring Framework đòi hỏi hàng loạt thao tác thủ công: cấu hình file web.xml, định nghĩa XML context, cài đặt kết nối cơ sở dữ liệu và triển khai file WAR lên Tomcat ngoài.

Ra mắt năm 2014, Spring Boot không thay thế Spring Framework mà đóng gói toàn diện 5 thành phần cốt lõi:

Java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  1. Spring Framework Core: Giữ nguyên toàn bộ 20 module nền tảng, không làm thay đổi các quy tắc IoC hay AOP.
  2. Starter Dependencies: Các dependency rỗng trong Maven/Gradle giúp gom cụm thư viện cần thiết theo use case (ví dụ spring-boot-starter-web tự động kéo Spring MVC, Jackson và Tomcat nhúng).
  3. Auto-Configuration: Cơ chế tự động nhận diện classpath và đăng ký các bean tương ứng nhờ các điều kiện @ConditionalOnClass hay @ConditionalOnMissingBean.
  4. Embedded Server: Tích hợp sẵn máy chủ Tomcat, Jetty hoặc Undertow vào file JAR thực thi, giúp khởi chạy ứng dụng trực tiếp qua lệnh java -jar app.jar.
  5. Production-Ready Actuator: Cung cấp sẵn các endpoint giám sát sức khỏe hệ thống (/actuator/health), metrics và cấu hình mà không cần viết thêm mã nguồn.

Một HTTP request di chuyển qua các lớp kiến trúc như thế nào?

Để hiểu rõ sự phối hợp giữa các module khi nhận một yêu cầu mạng, hãy quan sát hành trình của một HTTP request từ lúc chạm vào socket cho đến khi ghi dữ liệu xuống cơ sở dữ liệu:

Một request GET đi lần lượt qua tám lớp từ Tomcat Connector, filter chain, DispatcherServlet, HandlerMapping, controller, service tới repository; bên phải ghi triệu chứng lỗi sinh ra ở từng lớp, trong đó 401 dừng ngay tại filter chain trước khi tới controller

  1. Tomcat Connector: Nhận socket HTTP thô và bàn giao cho luồng xử lý.
  2. Servlet Filter Chain: Xử lý các tác vụ xuyên suốt như CORS, Logging và xác thực bảo mật (Spring Security). Nếu xác thực thất bại, request trả về HTTP 401 ngay tại đây mà không đi tiếp vào MVC.
  3. DispatcherServlet: Đóng vai trò Front Controller tiếp nhận request hợp lệ và điều phối.
  4. HandlerMapping & HandlerInterceptor: Ánh xạ đường dẫn URL đến phương thức controller tương ứng.
  5. RestController: Bóc tách tham số, chuyển đổi JSON thành DTO và gọi tầng Service.
  6. Service & Transaction Proxy: Thực thi logic nghiệp vụ và mở transaction DB thông qua proxy của spring-tx.
  7. Repository (Spring Data JPA) & Driver: Chuyển đổi thao tác thực thể thành câu lệnh SQL và gửi xuống cơ sở dữ liệu.

Nhờ việc phân định rõ từng lớp trách nhiệm, khi gặp lỗi 401 bạn biết cần kiểm tra Security Filter, gặp 404 xem lại HandlerMapping, và khi dữ liệu không lưu đúng cần kiểm tra tầng Transaction hoặc Repository.

Hệ sinh thái Spring qua các phiên bản tiến hóa ra sao?

Spring không ngừng cải tiến để thích nghi với các tiêu chuẩn mới của ngôn ngữ Java:

  • Spring 3.0 (2009): Chuyển dịch toàn diện từ cấu hình XML sang chú thích Java (Annotation-based như @Component, @Autowired).
  • Spring 4.0 (2013): Hỗ trợ Java 8, giới thiệu Lambda và generics-aware dependency injection.
  • Spring 5.0 (2017): Bổ sung ngăn xếp phản ứng Spring WebFlux hỗ trợ non-blocking I/O.
  • Spring 6.0 & Boot 3.0 (2022 trở đi): Nâng cấp chuẩn Java baseline lên Java 17 (khuyến nghị Java 21), hỗ trợ GraalVM native image và chuyển toàn bộ namespace từ javax.* sang jakarta.*.
Phiên bản BootPhiên bản FrameworkJava BaselineQuy ước Namespace
2.7.x (Legacy)5.3.xJava 8javax.*
3.0.x - 3.3.x6.0.x - 6.1.xJava 17jakarta.*
3.4.x (Chuẩn khóa học)6.2.xJava 17 (khuyến nghị 21)jakarta.*

Vì sao Spring vẫn chiếm ưu thế áp đảo trong phát triển backend?

Dù nhiều framework hiện đại ra đời sau như Quarkus hay Micronaut có tốc độ khởi động nhanh hơn trên lý thuyết, Spring vẫn giữ thị phần áp đảo nhờ 4 yếu tố then chốt:

  1. Hệ sinh thái toàn diện và ổn định: Tích hợp sẵn sàng với hàng trăm công nghệ lưu trữ, truyền thông điệp (Kafka, RabbitMQ) và đám mây.
  2. Khả năng kế thừa và cộng đồng khổng lồ: Mọi sự cố kỹ thuật đều có tài liệu hướng dẫn và kinh nghiệm giải quyết phong phú.
  3. Đột phá với Spring Boot 3.x: Tận dụng Virtual Threads (Java 21) và Coordinated Restore at Checkpoint (CRaC), giúp giảm thiểu khoảng cách về tài nguyên và hiệu năng.
  4. Hậu thuẫn chuyên nghiệp từ doanh nghiệp: Đội ngũ kỹ sư nòng cốt phát triển toàn thời gian với chu kỳ phát hành ổn định và cam kết hỗ trợ dài hạn (LTS).

Tóm tắt

  • EJB 2.x sụp đổ vì cấu trúc phức tạp và ràng buộc nền tảng; Spring giải phóng lập trình viên bằng mô hình POJO và IoC container.
  • IoC Container đảo ngược quyền quản lý đối tượng, chuyển trách nhiệm khởi tạo và kết nối phụ thuộc cho framework bên ngoài.
  • Spring Boot là tập hợp 5 thành phần hoàn chỉnh được đóng gói sẵn chứ không thay thế Spring Framework nền tảng.
  • Request đi qua chuỗi Filter bảo mật trước khi chạm vào DispatcherServlet và tầng Controller/Service.

Tự kiểm tra

Tự kiểm tra
0/5 câu đã trả lời
  1. Q1
    Một lập trình viên nhận định: "Spring Boot là phiên bản thay thế của Spring Framework nên không cần học Spring Framework nữa." Nhận định này có điểm nào chưa chính xác?
  2. Q2
    Liệt kê 3 module Spring Framework thường gặp nhất trong một dự án REST API CRUD tiêu chuẩn kèm annotation đặc trưng của từng module?
  3. Q3
    Trong 5 thành phần của Spring Boot, thành phần nào giúp chạy ứng dụng bằng lệnh java -jar mà không cần cài Tomcat rời, và thành phần nào tự tạo EntityManagerFactory khi có thư viện JPA?
  4. Q4
    Tại sao Spring Framework 6.0 và Spring Boot 3.0 lại thay đổi các import từ javax.* sang jakarta.*?
  5. Q5
    Khi một client gửi request bị từ chối với mã lỗi HTTP 401 Unauthorized, lớp nào trong kiến trúc đã chặn request này và vì sao breakpoint tại Controller không dừng lại?

Bài tiếp theo: Inversion of Control: Bản Chất Đảo Quyền Điều Khiển

Bài này có giúp bạn hiểu bản chất không?

Bài này đáng gửi cho bạn học cùng?

Copy link đã gắn nguồn — dán group, chat, hoặc LinkedIn.

Lộ trình Junior Java Backend Developer

Chặng 13/21 · Spring IoC, DI & Bean — bài 2/17 của chặng

Thảo luận & góp ý

Hỏi đáp về bài này

Bài tiếp theo

Inversion of Control: Đảo Ngược Quyền Kiểm Soát Trong Spring