1. Mở đầu :
Hiện tại như mình thấy thì có rất ít sách cũng như ebook đề cập đến kỹ thuật reflection trong programming, và cũng rất ít bạn biết về khái niệm này, trong khi hầu hết các framework lớn đều sử dụng. Không biết tới kỹ thuật này thì quả là một thiệt thòi không hề nhỏ . Hôm nay mình sẽ chia sẻ một ít kiến thức về reflection trong programming, hy vọng có ích cho các bạn. ( lưu ý với các ngôn ngữ script, context có thể khác đi ).
2. Khái niệm
Đã bao giờ bạn tự thắc mắc làm sao các framework MVC có thể mapping url request vào chính xác từng controller, hay làm sao spring lại có thể khởi tạo bean từ xml configuration or annotation, injection các giá trị vào bean? Tất cả là nhờ đến kỹ thuật reflection.Vậy reflection là gì?
Reflection là một quy tắc cho phép bạn có thể quan sát (observing) và thay đổi chương trình lúc runtime (wiki) . Hiểu nôm na có nghĩa là reflection cho phép bạn gán/modify mã code trong thời gian chạy, hay nói cách khác, nó cho phép chúng ta làm việc với “meta data” của một object.
Dựa vào reflection, chúng ta có thể kiểm tra xem một class A đã được định nghĩa chưa, Một method B thì có những annotation nào, call method của một object chưa biết tên lúc runtime mà không cần phải biết tên method đó lúc compile…
3. Example
Để hiểu rõ hơn về reflection thì chúng ta sẽ thử làm một ví dụ về reflection. À quên mất ngôn ngữ là java nhé các bạn ( .NET cũng tương tự như vậy nhé)
Bài toán : Giả sử bạn có 1 chương trình để thực hiện update dữ liệu vào CSDL. Vì mỗi CSDL khác nhau nên chúng có cơ chế làm việc khác nhau. Giả sử chúng ta có class MysqlJdbcDriver để thao tác với CSDL Mysql, MssqlJdbcDriver để thao tác với CSDL MsSql. 2 class này đều implement interface JdbcDriver, có 1 method là executeSql. Tùy vào config, chương trình sẽ tự động instance driver tương ứng để kết nối CSDL.
Interface JdbcDriver
public interface JdbcDriver {
void executeSql(String sql);
}
Class MysqlJdbcDriver
public class MysqlJdbcDriver implements JdbcDriver {
public void executeSql(String sql) {
System.out.println("Run on Mysql");
System.out.println("Execute sql : " + sql);
}
}
Class MssqlJdbcDriver
public class MssqlJdbcDriver implements JdbcDriver {
public void executeSql(String sql) {
System.out.println("Run on Mssql");
System.out.println("Execute sql : " + sql);
}
}
Class Program
public class Program {
/** Chú ý : chuỗi chứa class driver trong ví dụ này mình đang để hard code.
Thực tế thì nó có thể được load từ xml configuration, Annotation value,environment variable database or anywhere
*/
private String driverConfig = "MssqlJdbcDriver";
JdbcDriver jdbc;
public Program() throws Exception {
Class<?> driverClass = Class.forName(driverConfig);
// create object by name
this.jdbc = (JdbcDriver) driverClass.getConstructor().newInstance();
}
public void doUpdateData() {
this.jdbc.executeSql("update a set b = 'c'");
}
public static void main(String[] args) throws Exception {
Program p = new Program();
p.doUpdateData();
}
}
Chạy chương trình lên bạn sẽ thấy kết quả
Run on Mysql
Execute sql : update a set b = ‘c’
Thay đổi giá trị của driverConfig thành MssqlJdbcDriver, kết quả
Run on Mssql
Execute sql : update a set b = ‘c’
Bạn thấy đấy, nếu có thay đổi CSDL, thì class Program cũng không phải thay đổi gì. Chúng ta đã injection giá trị cho variable jdbc
Extra : Trong MVC, thì các url thường được mapping với các controller cụ thể. Các bạn cũng có thể dùng reflection để gửi request đến đúng Controller. Kiến trúc cũng rất đơn giản :
- Bạn có 1 Servlet sẽ handle toàn bộ request : url-pattern = * (web.xml)
- Trong Servlet này, dựa vào url request, bạn có thể xác định được url request tương ứng với class controller nào? tương ứng với method nào trong controller đó. giả sử request là /abc/def thì class controller sẽ là acb, method là def ( or bạn có thể tự đặt ra rule cho riêng mình )
- Khởi tạo đối tượng controller và call method tương ứng bằng reflection.
- Nhận kết quả trả về từ step 3, response về cho người dùng.
4. Kết luận :
Để hiểu rõ hơn thì các bạn cần phải thực hành nhiều hơn và gặp những bài toán cụ thể. Vì phần này đa số nằm ở các framework nên cũng ít va chạm. Hy vọng topic có ích cho các bạn. Mình chỉ chia sẻ những kiến thức mình biết. Nếu có gì sai mong các bạn góp ý. Thank all.