PDF:

Động lực học lập trình Java, Phần 3: Ứng dụng sự phản
chiếu
Xây dựng một khung công tác cho các đối số dòng lệnh
Dennis Sosnoski
Nhà tư vấn
Sosnoski Software Solutions, Inc.
04 12 2009
Xử lý đối số dòng lệnh là một trong những việc vặt khó chịu mà dường như vẫn tiếp tục xảy ra
xung quanh bất kể bạn đã phải giải quyết nó mất bao nhiêu lần trong quá khứ. Thay vì viết các
thay đổi của cùng mã lặp đi lặp lại, tại sao không sử dụng sự phản chiếu để đơn giản hóa công
việc xử lý đối số? Nhà tư vấn Java Dennis Sosnoski chỉ cho bạn thấy cách làm thế nào. Trong
bài này, Dennis phác thảo một thư viện mã nguồn mở, cho phép tạo các đối số dòng lệnh để tự
xử lý trên thực tế.
Xem thêm bài trong loạt bài này
Trong bài viết tháng trước, tôi đã giới thiệu Java Reflection API (API phản chiếu Java) và đã trình
bày qua một số khả năng cơ bản của nó. Tôi cũng xem xét kỹ hiệu năng phản chiếu và kết thúc
bằng một số hướng dẫn khi nào cần hay không cần sử dụng sự phản chiếu trong một ứng dụng.
Trong bài viết tháng này, tôi sẽ đi xa hơn bằng cách xem xét một ứng dụng dường như là một sự
phối hợp tốt cho những điểm mạnh và điểm yếu của sự phản chiếu: một thư viện để xử lý đối số
dòng lệnh.
Tôi sẽ bắt đầu bằng cách trước tiên xác định vấn đề cần giải quyết, sau đó thiết kế một giao diện
cho thư viện đó trước khi thực sự đi vào đoạn mã thực hiện. Kinh nghiệm thực tế của tôi về phát
triển thư viện chưa được cấu trúc như vậy -- tôi bắt đầu nỗ lực để làm đơn giản hóa mã hiện có trong
một họ các ứng dụng dùng một cơ sở mã chung, sau đó tổng quát hóa từ đó. Tuy nhiên, trình tự
theo đường thẳng "định nghĩa-thiết kế-xây dựng" trong bài viết này ngắn gọn hơn nhiều so với một
mô tả đầy đủ quá trình phát triển và trong quá trình tổ chức nó theo cách này tôi đã sửa lại một số
giả định ban đầu của tôi và xóa hết một vài khía cạnh của mã thư viện. Hy vọng rằng, bạn sẽ tìm
thấy nó có ích như là một mô hình để phát triển các ứng dụng dựa trên sự phản chiếu của riêng bạn.
© Copyright IBM Corporation 2009
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Nhẫn hiệu đăng ký
Trang 1 của 11
developerWorks®
ibm.com/developerWorks/vn/
Xác định vấn đề
Tôi đã viết nhiều ứng dụng Java bằng cách sử dụng các đối số từ dòng lệnh. Hầu hết được bắt đầu
thực sự nhỏ, nhưng một số đã kết thúc phát triển ngày càng xa kế hoạch ban đầu của tôi. Có một
mô hình chuẩn mà tôi đã quan sát thấy theo cách quá trình này hoạt động với tôi:
Đừng bỏ lỡ phần còn lại của loạt bài này
Phần 1, "Các lớp Java và nạp lớp" (04.2003)
Phần 2, "Giới thiệu sự phản chiếu" (06.2003)
Phần 4, "Chuyển đổi lớp bằng Javassist" (09.2003)
Phần 5, "Việc chuyển các lớp đang hoạt động" (02.2004)
Phần 6, "Các thay đổi hướng-khía cạnh với Javassist" (03.2004)
Phần 7, "Kỹ thuật bytecode với BCEL" (04.2004)
Phần 8, "Thay thế sự phản chiếu bằng việc tạo mã" (06.2004)
1. Bắt đầu với một hoặc hai đối số cần thiết theo một thứ tự cụ thể.
2. Hãy suy nghĩ về nhiều thứ mà ứng dụng nên làm, sau đó thêm vào nhiều đối số nữa.
3. Cảm thấy mệt mỏi về việc gõ tất cả các đối số mỗi lần, vì thế hãy tạo ra một số đối số tùy chọn,
với các giá trị mặc định.
4. Quên thứ tự của các đối số, do đó thay đổi mã để cho phép chúng theo thứ tự bất kỳ.
5. Cung cấp ứng dụng cho những người khác đang quan tâm. Họ không biết những gì các đối số
có nghĩa vụ phải làm, do đó, thêm phần kiểm tra lỗi tốt hơn và "trợ giúp" các mô tả cho các
đối số.
Theo thời gian tôi đi đến bước 5 tôi thường thấy tiếc là tôi đã bắt đầu toàn bộ quá trình tại vị trí đầu
tiên. May mắn thay, tôi có xu hướng quên các giai đoạn sau khá nhanh và trong vòng một hoặc hai
tuần tôi sẽ nghĩ về một ứng dụng dòng lệnh khác đơn giản một chút mà tôi muốn có. Sau đó nó chỉ
còn là một vấn đề thời gian trước khi lặp đi lặp lại toàn bộ chu kỳ khó chịu đó.
Có một số thư viện có sẵn để trợ giúp việc xử lý đối số dòng lệnh. Tuy nhiên, tôi sẽ bỏ qua chúng và
đi theo cách riêng của mình trong bài viết này. Đây không phải (chỉ) vì tôi có một quan điểm "không
sáng tác ở đây", mà là để sử dụng việc xử lý đối số như là một ví dụ. Khi điều đó xảy ra, các điểm
mạnh và điểm yếu của sự phản chiếu là một sự phối hợp tốt với các yêu cầu cho một thư viện xử lý
đối số. Cụ thể là, một thư viện xử lý đối số:
•
•
•
•
Cần một giao diện linh hoạt để hỗ trợ một loạt các ứng dụng.
Phải dễ dàng cấu hình cho mỗi ứng dụng.
Không đòi hỏi hiệu năng cao nhất, vì các đối số chỉ được xử lý một lần.
Không có vấn đề bảo mật truy cập, vì các ứng dụng dòng lệnh thường chạy mà không có một
trình quản lý bảo mật.
Mã phản chiếu thực tế trong thư viện này trình bày chỉ một phần nhỏ việc của việc thực hiện đầy đủ,
vì vậy tôi sẽ chủ yếu tập trung vào các khía cạnh hầu như có liên quan đến sự phản chiếu. Nếu bạn
muốn tìm hiểu thêm về thư viện này (và có lẽ sử dụng nó cho các ứng dụng dòng lệnh đơn giản của
riêng bạn), bạn sẽ tìm các liên kết tới các trang Web trong phần Tài nguyên.
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 2 của 11
ibm.com/developerWorks/vn/
developerWorks®
Hỏi chuyên gia: Dennis Sosnoski về các vấn đề JVM và
bytecode
Đối với các ý kiến hay các câu hỏi về tài liệu được trình bày trong loạt bài này, cũng như bất
cứ điều gì khác có liên quan đến Java bytecode, định dạng lớp nhị phân Java hoặc các vấn
đề JVM chung, hãy truy cập vào diễn đàn thảo luận JVM và Bytecode, do Dennis Sosnoski
kiểm soát.
Phác thảo một thiết kế
Có lẽ cách thuận tiện nhất để một ứng dụng truy cập dữ liệu đối số là thông qua các trường của
đối tượng chính của ứng dụng. Ví dụ, giả sử bạn đang viết một ứng dụng tạo ra các kế hoạch kinh
doanh. Bạn có thể muốn sử dụng một cờ boolean (toán tử boolean) để kiểm soát xem kế hoạch
kinh doanh có ngắn gọn hay dài dòng không, một int cho doanh thu năm đầu tiên, một float cho
tỷ lệ tăng trưởng doanh thu hỗn hợp dự kiến và một String cho việc mô tả sản phẩm. Tôi sẽ gọi các
biến này, đó là các biến có ảnh hưởng đến hoạt động của các tham số ứng dụng để phân biệt chúng
với các đối số thực tế (các giá trị cho các biến tham số) được cung cấp trên dòng lệnh. Việc sử dụng
các trường cho các tham số này sẽ làm cho chúng dễ dàng có sẵn tại bất kỳ điểm nào trong mã
ứng dụng mà ở đó cần chúng . Nó cũng dễ dàng để thiết lập các giá trị mặc định cho bất kỳ các
tham số nào ngay tại điểm định nghĩa khi sử dụng các trường, như thể hiện trong Liệt kê 1:
Liệt kê 1. Trình tạo kế hoạch kinh doanh (liệt kê một phần)
public class PlanGen {
private boolean m_isConcise;
// rarely used, default false
private int m_initialRevenue = 1000; // thousands, default is 1M
private float m_growthRate = 1.5;
// default is 50% growth rate
private String m_productDescription = // McD look out, here I come
"eFood - (Really) Fast Food Online";
...
private int revenueForYear(int year) {
return (int)(m_initialRevenue * Math.pow(m_growthRate, year-1));
}
...
Sự phản chiếu sẽ cho truy cập trực tiếp đến các trường riêng, cho phép thư viện xử lý đối số thiết
lập các giá trị mà không có bất kỳ kết nối đặc biệt nào vào mã ứng dụng. Tuy nhiên, tôi rất cần một
số đường cho thư viện để liên kết các trường này tới các đối số dòng lệnh cụ thể. Trước khi tôi có
thể định nghĩa cách liên kết này giữa một đối số và một trường được truyền dẫn đến thư viện, lần
đầu tiên tôi cần phải quyết định cách tôi muốn định dạng các đối số dòng lệnh.
Đối với bài viết này, tôi sẽ xác định một định dạng dòng lệnh, đó là một phiên bản đơn giản hóa
các quy tắc UNIX. Các giá trị đối số cho các tham số có thể được cung cấp theo thứ tự bất kỳ, với
một gạch nối trên đầu để chỉ thị rằng một đối số cho một hoặc nhiều cờ tham số ký tự đơn (như
trái ngược với các giá trị tham số thực tế). Đối với trình tạo kế hoạch kinh doanh (business plan
generator), tôi sẽ chọn các ký tự cờ của các tham số này:
• c -- kế hoạch ngắn gọn.
• f -- doanh thu năm đầu tiên (hàng nghìn Đôla Mỹ-$).
• g -- tốc độ tăng trưởng (hệ số nhân hàng năm).
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 3 của 11
developerWorks®
ibm.com/developerWorks/vn/
• n -- tên sản phẩm.
Các tham số boolean chỉ cần chính ký tự cờ của nó để thiết lập một giá trị, nhưng các kiểu khác
của các tham số yêu cầu một số sự phân loại thông tin đối số bổ sung. Tôi sẽ chỉ viết thêm vào một
giá trị của một đối số bằng số trực tiếp sau ký tự cờ tham số (có nghĩa là không thể sử dụng các số
làm các ký tự cờ), trong khi các tham số có giá trị-String mà tôi sẽ sử dụng đối số tiếp theo ký tự
cờ trên dòng lệnh như là giá trị thực tế. Cuối cùng, nếu có các tham số cần thiết (như là một tên tệp
kết quả cho trình tạo kế hoạch kinh doanh), tôi sẽ giả định các giá trị đối số cho các tham số này
theo sau các giá trị tham số tùy chọn trên dòng lệnh. Căn cứ vào các quy tắc này, một dòng lệnh
cho trình tạo kế hoạch kinh doanh có thể trông như sau:
java PlanGen -c -f2500 -g2.5 -n "iSue4U - Litigation at Internet Speed" plan.txt
Khi tất cả được đặt cùng nhau, ý nghĩa của từng đối số là:
•
•
•
•
•
-c -- tạo kế hoạch ngắn gọn.
-f2500 -- doanh thu năm đầu tiên là 2.500.000 đô la Mỹ.
-g2.5 -- tốc độ tăng trưởng là 250 phần trăm mỗi năm.
-n "iSue4U . . ." -- tên sản phẩm là "iSue4U . . ."
plan.txt --tên của tập tin kết quả cần thiết.
Vào lúc này, tôi đã có một đặc tả chức năng cơ bản cho thư viện xử lý đối số. Bước tiếp theo là xác
định một giao diện cụ thể cho mã ứng dụng để sử dụng thư viện.
Chọn giao diện
Bạn có thể điều khiển việc xử lý thực tế các đối số dòng lệnh với một cuộc gọi, nhưng trước tiên ứng
dụng cần một cách để định nghĩa các tham số cụ thể của nó cho thư viện. Các tham số này có thể
có một số kiểu khác nhau (trong trường hợp ví dụ trình tạo kế hoạch kinh doanh, chúng có thể là
boolean, int, float và java.lang.String). Mỗi kiểu cũng có thể có một số yêu cầu đặc biệt. Ví dụ,
thật thú vị để cho phép các tham số boolean được định nghĩa là false (sai) nếu có ký tự cờ này,
thay vì luôn luôn true (đúng) nếu có ký tự cờ này. Cũng sẽ rất có ích để xác định một phạm vi hợp
lệ cho một giá trị int.
Tôi sẽ xử lý các yêu cầu khác nhau này bằng cách sử dụng một lớp cơ sở cho tất cả các định nghĩa
tham số, phân lớp nó cho từng kiểu tham số cụ thể. Cách tiếp cận này cho phép ứng dụng cung cấp
các định nghĩa tham số cho thư viện như là một mảng các cá thể của lớp định nghĩa tham số cơ
bản, trong khi các định nghĩa thực tế có thể sử dụng lớp con cụ thể phối hợp với từng kiểu tham số.
Với ví dụ về trình tạo kế hoạch kinh doanh, điều này có thể đưa ra dạng được hiển thị trong Liệt kê
2:
Liệt kê 2. Các định nghĩa tham số cho trình tạo kế hoạch kinh doanh
private
new
new
new
new
}
static final ParameterDef[] PARM_DEFS = {
BoolDef('c', "m_isConcise"),
IntDef('f', "m_initialRevenue", 10, 10000),
FloatDef('g', "m_growthRate", 1.0, 100.0),
StringDef('n', "m_productDescription")
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 4 của 11
ibm.com/developerWorks/vn/
developerWorks®
Với các tham số được phép đã định nghĩa trong một mảng, cuộc gọi từ chương trình ứng dụng tới
mã xử lý đối số có thể được duy trì càng đơn giản như một cuộc gọi duy nhất tới một phương thức
tĩnh càng tốt. Để tính đến các đối số thêm vào ngoài những cái đã được xác định trong mảng tham
số (hoặc các giá trị cần thiết hoặc các tập các giá trị chiều dài thay đổi), tôi sẽ có cuộc gọi trả về số
lượng thực của các đối số được xử lý. Điều này cho phép kiểm tra ứng dụng cho các đối số bổ sung
và sử dụng chúng một cách thích hợp. Kết quả cuối cùng trông như Liệt kê 3:
Liệt kê 3. Sử dụng thư viện
public class PlanGen
{
private static final ParameterDef[] PARM_DEFS = {
...
};
public static void main(String[] args) {
// if no arguments are supplied, assume help is needed
if (args.length > 0) {
// process arguments directly to instance
PlanGen inst = new PlanGen();
int next = ArgumentProcessor.processArgs
(args, PARM_DEFS, inst);
// next unused argument is output file name
if (next >= args.length) {
System.err.println("Missing required output file name");
System.exit(1);
}
File outf = new File(args[next++]);
...
} else {
System.out.println("\nUsage: java PlanGen " +
"[-options] file\nOptions are:\n c concise plan\n" +
"f first year revenue (K$)\n g growth rate\n" +
"n product description");
}
}
}
Phần duy nhất còn lại là việc xử lý tạo báo cáo lỗi (chẳng hạn như một ký tự cờ tham số không rõ
hoặc một giá trị số ngoài dải). Với mục đích này, tôi sẽ xác định ArgumentErrorException như là
một lỗi ngoại lệ không được kiểm tra được đưa ra nếu một trong các lỗi này xảy ra. Nếu lỗi ngoại lệ
này không được nhận ra, nó sẽ ngay lập tức làm hỏng ứng dụng với một thông báo lỗi và vết tích
ngăn xếp được kết xuất trên bàn điều khiển. Như là một sự lựa chọn, bạn có thể nhận ra lỗi ngoại lệ
này trực tiếp trong mã của bạn và xử lý nó bằng một số cách khác (ví dụ, có thể in ra các thông báo
lỗi thực tế cùng với việc thông tin về cách sử dụng).
Thực hiện thư viện
Đối với thư viện để sử dụng sự phản chiếu như đã lập kế hoạch, cần phải tìm kiếm các trường được
xác định bằng mảng các định nghĩa tham số và sau đó lưu trữ các giá trị thích hợp tới các trường
này từ các đối số dòng lệnh tương ứng. Nhiệm vụ này có thể được xử lý bằng cách tìm kiếm thông
tin trường khi cần thiết cho các đối số dòng lệnh thực tế, nhưng thay vào đó tôi đã thực hiện một sự
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 5 của 11
developerWorks®
ibm.com/developerWorks/vn/
lựa chọn để tách việc tìm kiếm khỏi cách sử dụng. Tôi sẽ tìm thấy tất cả các trường trước, sau đó chỉ
cần sử dụng thông tin đã được tìm thấy trong quá trình xử lý các đối số.
Tìm trước tất cả các trường là một bước lập trình an toàn để loại bỏ một trong các vấn đề tiềm
năng khi dùng phản chiếu. Nếu tôi chỉ tìm kiếm các trường khi cần thiết, thật dễ dàng để phá vỡ
một định nghĩa tham số (ví dụ, bằng cách không gõ tên trường tương ứng) mà không nhận ra rằng
có bất cứ điều gì đã sai. Sẽ không có các lỗi thời gian-dịch nào vì tên trường được chuyển qua như
các String, và thậm chí chương trình sẽ thực hiện tốt miễn là không có đối số khớp với định nghĩa
tham số bị ngắt đã được xác định trên dòng lệnh. Kiểu lỗi có đánh dấu này có thể dễ dàng làm cho
việc chuyển dịch mã bị hỏng.
Dựa vào đó tôi muốn tìm thông tin trường trước khi xử lý các đối số trên thực tế, Liệt kê 4 cho thấy
việc thực hiện lớp cơ bản cho các định nghĩa tham với một phương thức bindToClass() để xử lý tìm
kiếm trường.
Liệt kê 4. Lớp cơ sở cho các định nghĩa tham số
public abstract class ParameterDef
{
protected char m_char;
protected String m_name;
protected Field m_field;
// argument flag character
// parameter field name
// actual parameter field
protected ParameterDef(char chr, String name) {
m_char = chr;
m_name = name;
}
public char getFlag() {
return m_char;
}
protected void bindToClass(Class clas) {
try {
// handle the field look up and accessibility
m_field = clas.getDeclaredField(m_name);
m_field.setAccessible(true);
} catch (NoSuchFieldException ex) {
throw new IllegalArgumentException("Field '" +
m_name + "' not found in " + clas.getName());
}
}
public abstract void handle(ArgumentProcessor proc);
}
Việc thực hiện thư viện thực tế bao gồm một vài lớp ngoài những gì mà tôi đã đề cập trong bài viết
này. Tôi sẽ không duyệt toàn bộ danh sách ở đây, vì hầu hết không liên quan đến khía cạnh phản
chiếu của thư viện. Tôi sẽ đề cập đến những gì mà tôi đã chọn để lưu trữ đối tượng đích như là một
trường của lớp ArgumentProcessor và thực hiện cài đặt thực tế một trường tham số trong lớp này.
Cách tiếp cận này đưa ra một mẫu đơn giản cho việc xử lý đối số: lớp ArgumentProcessor quét các
đối số để tìm các cờ tham số, tìm kiếm định nghĩa tham số tương ứng cho mỗi cờ (mà cờ đó sẽ luôn
là một lớp con của ParameterDef) và gọi phương thức handle() của định nghĩa đó. Phương thức
handle() lần lượt gọi một phương thức setValue() của ArgumentProcessor sau khi giải thích giá trị
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 6 của 11
ibm.com/developerWorks/vn/
developerWorks®
đối số. Liệt kê 5 cho thấy một phiên bản một phần của lớp ArgumentProcessor bao gồm các cuộc
gọi liên kết tham số trong hàm tạo và phương thức setValue():
Liệt kê 5. Liệt kê một phần lớp thư viện chính
public class ArgumentProcessor
{
private Object m_targetObject; // parameter value object
private int m_currentIndex;
// current argument position
...
public ArgumentProcessor(ParameterDef[] parms, Object target) {
// bind all parameters to target class
for (int i = 0; i < parms.length; i++) {
parms[i].bindToClass(target.getClass());
}
// save target object for later use
m_targetObject = target;
}
public void setValue(Object value, Field field) {
try {
// set parameter field value using reflection
field.set(m_targetObject, value);
} catch (IllegalAccessException ex) {
throw new IllegalArgumentException("Field " + field.getName() +
" is not accessible in object of class " +
m_targetObject.getClass().getName());
}
}
public void reportArgumentError(char flag, String text) {
throw new ArgumentErrorException(text + " for argument '" +
flag + "' in argument " + m_currentIndex);
}
public static int processArgs(String[] args,
ParameterDef[] parms, Object target) {
ArgumentProcessor inst = new ArgumentProcessor(parms, target);
...
}
}
Cuối cùng, Liệt kê 6 cho thấy việc thực hiện một phần của lớp con định nghĩa tham số cho các giá
trị tham số int. Điều này có cả việc ghi đè của phương thức bindToClass() lớp cơ sở (từ Liệt kê 4)
phương thức này trước tiên gọi thực hiện lớp cơ sở và sau đó kiểm tra xem trường đã tìm thấy có
ăn khớp với kiểu dự kiến không. Các lớp con cho các kiểu tham số cụ thể khác (boolean, float,
String, v.v) là rất giống nhau.
Liệt kê 6.Lớp định nghĩa tham số int
public class IntDef extends ParameterDef
{
private int m_min;
// minimum allowed value
private int m_max;
// maximum allowed value
public IntDef(char chr, String name, int min, int max) {
super(chr, name);
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 7 của 11
developerWorks®
ibm.com/developerWorks/vn/
m_min = min;
m_max = max;
}
protected void bindToClass(Class clas) {
super.bindToClass(clas);
Class type = m_field.getType();
if (type != Integer.class && type != Integer.TYPE) {
throw new IllegalArgumentException("Field '" + m_name +
"'in " + clas.getName() + " is not of type int");
}
}
public void handle(ArgumentProcessor proc) {
// set up for validating
boolean minus = false;
boolean digits = false;
int value = 0;
// convert number supplied in argument list to 'value'
...
// make sure we have a valid value
value = minus ? -value : value;
if (!digits) {
proc.reportArgumentError(m_char, "Missing value");
} else if (value < m_min || value > m_max) {
proc.reportArgumentError(m_char, "Value out of range");
} else {
proc.setValue(new Integer(value), m_field);
}
}
}
Đóng lại thư viện
Trong bài viết này, tôi đã duyệt qua việc thiết kế một thư viện để xử lý các đối số dòng lệnh như
một ví dụ về sự phản chiếu đang hoạt động. Thư viện này tạo ra một sự minh hoạ tốt về cách sử
dụng sự phản chiếu có hiệu quả -- nó làm đơn giản mã ứng dụng mà không phải hy sinh hiệu năng
đáng kể. Phải từ bỏ bao nhiêu hiệu năng? Trong một số phép thử nghiệm nhanh trên hệ thống phát
triển của tôi, một chương trình thử nghiệm đơn giản đã lấy trung bình dài hơn khoảng 40 giây để
thực hiện việc xử lý đối số khi sử dụng thư viện đầy đủ, như được so sánh với việc xử lý không có đối
số nào. Phần lớn thời gian đó biểu diễn việc nạp các lớp thư viện và các lớp khác được mã thư viện
sử dụng, vì vậy ngay cả với các ứng dụng có nhiều tham số dòng lệnh được định nghĩa và nhiều giá
trị đối số, nó không thể xấu hơn điều này. Đối với các ứng dụng dòng lệnh của tôi, 40 giây thêm vào
không phải là một cái gì đó mà tôi sắp thông báo.
Mã thư viện đầy đủ có sẵn từ đường liên kết trong phần Tài nguyên. Nó bao gồm một số tính năng
mà tôi đã để ngoài bài viết này, bao gồm nhiều điều thú vị như là kết nối để dễ dàng tạo ra một
danh sách có định dạng của cờ và các mô tả tham số để giúp cung cấp các hướng dẫn cách sử
dụng cho một ứng dụng. Bạn cứ việc sử dụng thư viện đó trong các chương trình của riêng bạn và
mở rộng nó theo bất kỳ cách nào mà bạn thấy có ích.
Bây giờ tôi đã trình bày các điều cơ bản của các lớp Java trong Phần 1 và các nguyên tắc Java
Reflection API trong Phần 2 và Phần 3, phần còn lại của loạt bài này sẽ tránh đi theo con đường ít
người qua lại về thao tác bytecode. Tôi sẽ bắt đầu dễ dàng trong Phần 4 với việc xem xét về thư viện
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 8 của 11
ibm.com/developerWorks/vn/
developerWorks®
Javassist thân thiện với người dùng để làm việc với các lớp nhị phân. Bạn có muốn thử các phương
thức chuyển đổi không, chỉ là miễn cưỡng để bắt đầu lập trình theo bytecode? Javassist có thể chỉ
là công cụ phù hợp với các nhu cầu của bạn. Hãy tìm hiểu Javassist là như thế nào vào tháng tới.
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 9 của 11
developerWorks®
ibm.com/developerWorks/vn/
Tài nguyên
• Tải về thư viện xử lý đối số đầy đủ (được gọi JArgp) từ trang dự án Sourceforge.
• Việc sử dụng rộng rãi sự phản chiếu có thể gây tác hại cho hiệu năng của khung công tác. Với
một ví dụ đồ họa và một số cuộc thảo luận liên quan, xem các bài viết liên kết dữ liệu (data
binding) XML của tác giả "Liên kết dữ liệu, Phần 2: Hiệu năng" (developerWorks, 01.2003) và
"Liên kết dữ liệu, Phần 3: kiến trúc JiBX" (developerWorks, 04.2003).
• Để có hướng dẫn sâu về cách sử dụng sự phản chiếu, hãy thử làm theo API phản chiếu của
Dale Green trong Hướng dẫn Java của Sun.
• Tìm thêm hàng trăm tài nguyên công nghệ Java trên vùng công nghệ Java của
developerWorks.
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 10 của 11
ibm.com/developerWorks/vn/
developerWorks®
Đôi nét về tác giả
Dennis Sosnoski
Dennis Sosnoski là một nhà tư vấn và nhà trợ giúp đào tạo chuyên về các dịch vụ
Web và SOA dựa trên-Java. Kinh nghiệm phát triển phần mềm chuyên nghiệp của ông
trải suốt hơn 30 năm qua, với một thập kỉ cuối tập trung vào các công nghệ XML và
Java phía máy chủ. Dennis là nhà phát triển hàng đầu về dụng cụ liên kết dữ liệu XML
JiBX mã nguồn mở, cũng là một người có duyên nợ với khung công tác của các dịch
vụ Web Apache Axis2. Ông cũng là một trong những thành viên của nhóm chuyên gia
đặc tả kỹ thuật của Jax-WS 2.0 và JAXB 2.0. Xem trang web của ông để có thông tin
về các dịch vụ đào tạo và tư vấn của ông.
© Copyright IBM Corporation 2009
(www.ibm.com/legal/copytrade.shtml)
Nhẫn hiệu đăng ký
(www.ibm.com/developerworks/vn/ibm/trademarks/)
Động lực học lập trình Java, Phần 3: Ứng dụng sự phản chiếu
Trang 11 của 11