-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local

Thật sự trìu tượng
Lần đầu mình tiếp xúc với khái niêm tiêm phụ thuộc (DI - Dependency Injection) là khi mới ra trường. Thật sự là nó quá khó hiểu. Lúc đó mình cũng chỉ hiểu DI là cái gì đó tương đương với @Inject
annotation của JavaEE hay một cái file cấu hình xml của Spring. Và chỉ đến khi làm thư viện, mình mới thực sự hiểu, à hoá ra nó cũng chỉ là một cách thức khởi tạo đối tượng thay thế cho hàm setter mà thôi. Tuy nhiên đơn giản không có nghĩa là nó it tác dụng, mà ngược lại tác dụng của nó là siêu to khổng lồ.
Bài toán thực tế
Giả sử ứng dụng quản lý sách của chúng ta sẽ có 3 lớp:
- BookRepository: để truy xuất cơ sở dữ liệu
- BookService: để thực hiện một số nghiệp vụ, xử lý logic trước khi ghi truy xuất cơ sở dữ liệu
- BookController: để nhận request, gọi xuống tầng service để xử lý logic và trả lại response cho client
Sơ đồ lớp phụ thuộc sẽ thế này:

Và source code sẽ như sau:
public class BookRepository {
public void save(Book book) {
System.out.println("saved book: " + book);
}
}
public class BookService {
private final BookRepository bookRepository;
public void saveBook(Book book) {
bookRepository.save(book);
}
}
public class BookController {
private final BookService bookService;
public void saveBook(Book book) {
bookService.saveBook(book);
}
}
Ứng dụng của chúng ta sẽ chạy thông qua hàm main
kinh điển như thế này:
final BookRepository bookRepository = new BookRepository();
final BookService bookService = new BookService();
bookService.setBookRepository(bookRepository);
final BookController bookController = new BookController();
bookController.setBookService(bookService);
bookController.saveBook(new Book(1L, "EzyFox in action"));
Phân tích vấn đề
Chúng ta có thể thấy rằng hàm main này khá phức tạp so với những gì mà chúng ta thấy khi lập trình với Spring Boot. Rõ ràng là chúng ta phải tự mình khởi tạo mọi đối tượng và set các đối tượng phụ thuộc vào nhau. Với những ứng dụng đơn giản thì không sao, nhưng với những ứng dụng với hàng trăm hàng nghìn lớp theo mô hình thế này:

Thì có lẽ việc phải khởi tạo từng đối tượng và set chúng lại sẽ không khác gì chúng ta phải đi xây kim tự tháp vậy, thực sự rất khó khăn. Đây chính là lúc DI ra đời, hay nói chính xác hơn là tự động tiêm phụ thuộc (Dendency Injection Atomatically) đã ra đời.
Mục tiêu ra đời
Về cơ bản thì DI ra đời với 2 mục tiêu chính:
- Tự động khởi tạo các đối tượng và tiêm (inject) các đối tượng phụ thuộc vào với nhau mà không cần bất cứ sự can thiệp nào từ lập trình viên
- Giúp chúng ta giải quyến vấn đề tương thích ngược (IoC) mà mình sẽ nói ở bài sau
Áp dụng DI
Nào bây giờ hãy quay trở lại bài toán quản lý sách, chúng ta sẽ sử dụng thư viện ezyfox-bean. Thư viện này là sự kết hợp giữa java reflection
và java just in time (JIT)
, nó sẽ giúp chúng ta dễ dàng áp dụng DI chỉ với vài dòng code:
final EzyBeanContext beanContext = EzyBeanContext.builder()
.scan("com.tvd12.ezyfox.example.bean")
.build();
Bản chất bên trong của những dòng code này là nó sẽ đi tìm kiếm các lớp được đánh dấu với @EzySingleton
annotation để khởi tạo. Và muốn sử dụng chúng ta chỉ cần làm thế này:
final BookController bookController = (BookController)beanContext.getBean(BookController.class);
bookController.saveBook(new Book(1L, "EzyFox in action"));
Bạn có thể thấy rằng việc khởi tạo các lớp và gọi hàm set đã biến mất, và cho dù có hàng trăm, hàng nghìn lớp thì với sự hỗ trợ của các thư viện lập trình DI, mọi thứ cũng chỉ đơn giản là một vài dòng code mà thôi.
Kết luận
Dependency Injection ngày nay là một thứ không thể thiếu, nó sẽ giúp chúng ta hoàn toàn thoát khỏi việc khởi tạo và set các phụ thuộc cho các lớp. Tuy nhiên trong số các ngôn ngữ lập trình thì hiện nay vẫn chỉ có Java là mạnh nhất với các bộ thư viện hỗ trợ scan và đọc annotation, C# cũng có nhiều thư viện Entity hỗ trợ DI nhưng chưa triệt để được bằng Java, còn các ngôn ngữ khác thì đa phần chúng ta vẫn phải tự khởi tạo và set. Nhưng dù là ở ngôn ngữ nào, thì chúng ta hãy luôn tìm cách để làm DI nhé, nó thực sự có sức mạnh ghê gớm.
Tham khảo
-
Design Pattern
- Singleton Design Pattern
- Factory Design Pattern
- Factory Method Design Pattern
- Abstract Factory Design Pattern
- Builder Design Pattern
- Prototype Design Pattern
- Object Pool Design Pattern
- Chain of Responsibility Design Pattern
- Command Design Pattern
- Interpreter Design Pattern
- Iterator Design Pattern
- Mediator Design Pattern
- Memento Design Pattern
- Observer Design Pattern
- Observer Design Pattern - Xử Lý Exception
- Strategy Design Pattern
- Template Method Design Pattern
- Visitor Design Pattern
- Null Object Design Pattern
- Adapter Design Pattern
- Bridge Design Pattern
- Composite Design Pattern
- Decorator Design Pattern
- Flyweight Design Pattern
- Proxy Design Pattern
- S.O.L.I.D
- Clean code
- Lập trình socket
- Java Core
- Multi-Thread
- Spring
- Java Web
- Memory Caching
- Message Queue
- DevOps
- Xây dựng một nền tảng
- MongoDB
- MySQL timestamp
- Properties vs yaml
- Kotlin
- Lập Trình Machine Learning với PyTorch
- Mã Nguồn Mở
- Ezy HTTP
- Free Chat
- Một số kinh nghiệm với Git
- Review cho đồng nghiệp!
- Setup Dev Environment
- Hello World
- Create a Server Project
- Handle Client Requests
- Using ezyfox-server-csharp-client
- Using ezyfox-es6-client
- Client React.js Interaction
- Build And Deploy In Local