JavaBeans và Cơ Chế Nội Tỉnh

Cơ chế nội tỉnh (Introspection) trong JavaBeans cho phép chương trình phân tích các thuộc tính, sự kiện và phương thức của một lớp (Bean) vào thời gian chạy mà không cần biết mã cụ thể. Điều này chủ yếu dựa trên gói java.beans.

1. Các Khái Niệm Chính và Lớp Liên Quan

  • JavaBean: Một lớp tuân theo quy tắc nhất định (thuộc tính riêng tư, hàm dựng không tham số, getter/setter công khai).
  • Nội Tỉnh: Công cụ để lấy siêu dữ liệu của Bean.
  • Thông Tin Bean: Mô tả tất cả thuộc tính, phương thức và sự kiện của Bean.
  • Mô Tả Thuộc Tính: Siêu dữ liệu của từng thuộc tính (tên, kiểu, getter/setter).
  • Mô Tả Phương Thức: Siêu dữ liệu của từng phương thức.

2. Ví Dụ Minh Họa Toàn Diện

Ví dụ dưới đây sẽ minh họa cách sử dụng các API để đọc thông tin thuộc tính, lấy giá trị động và thiết lập giá trị động.

Bước 1: Định Nghĩa Một JavaBean Tiêu Chuẩn

public class Nguoi {
    private String ten;
    private int tuoi;
    private boolean dangHoatDong;

    public Nguoi() {}

    public Nguoi(String ten, int tuoi) {
        this.ten = ten;
        this.tuoi = tuoi;
    }

    public String getTen() { return ten; }
    public void setTen(String ten) { this.ten = ten; }

    public int getTuoi() { return tuoi; }
    public void setTuoi(int tuoi) { this.tuoi = tuoi; }

    public boolean isDangHoatDong() { return dangHoatDong; }
    public void setDangHoatDong(boolean dangHoatDong) { this.dangHoatDong = dangHoatDong; }
}

Bước 2: Sử Dụng Introspector và PropertyDescriptor Để Hoạt Động

import java.beans.*;
import java.lang.reflect.Method;

public class DemoNgonNguJavaBeans {
    public static void main(String[] args) {
        try {
            Nguoi nguoi = new Nguoi("Nguyen Van A", 30);
            nguoi.setDangHoatDong(true);

            System.out.println("=== 1. Lấy Thông Tin Tổng Thể Của Bean (BeanInfo) ===");
            BeanInfo beanInfo = Introspector.getBeanInfo(Nguoi.class, Object.class);

            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

            for (PropertyDescriptor pd : propertyDescriptors) {
                String tenThuocTinh = pd.getName();
                Class kieuThuocTinh = pd.getPropertyType();
                
                System.out.println("Tên thuộc tính: " + tenThuocTinh);
                System.out.println("  - Kiểu: " + kieuThuocTinh.getSimpleName());
                
                Method phuongThucDoc = pd.getReadMethod();
                Method phuongThucGhi = pd.getWriteMethod();

                if (phuongThucDoc != null) {
                    System.out.println("  - Getter: " + phuongThucDoc.getName());
                    Object giaTri = phuongThucDoc.invoke(nguoi);
                    System.out.println("  - Giá trị hiện tại: " + giaTri);
                } else {
                    System.out.println("  - Chỉ viết (không có Getter)");
                }

                if (phuongThucGhi != null) {
                    System.out.println("  - Setter: " + phuongThucGhi.getName());
                } else {
                    System.out.println("  - Chỉ đọc (không có Setter)");
                }
                System.out.println("-------------------------");
            }

            System.out.println("\n=== 2. Thao Tác Với Thuộc Tính Cụ Thể (Tạo PropertyDescriptor Trực Tiếp) ===");

            String tenThuocTinhCanDoi = "tuoi";
            PropertyDescriptor pd = new PropertyDescriptor(tenThuocTinhCanDoi, Nguoi.class);
            
            Method setter = pd.getWriteMethod();
            setter.invoke(nguoi, 40); 
            
            System.out.println("Sau khi sửa đổi, kiểm tra bằng Getter: " + pd.getReadMethod().invoke(nguoi));

        } catch (IntrospectionException e) {
            System.err.println("Lỗi nội tỉnh: Có thể tên thuộc tính sai hoặc không tuân thủ quy tắc JavaBean.");
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3. Các Tình Huống Ứng Dụng Phổ Biến

  1. Phát Triển Framework: Spring, Hibernate, MyBatis dùng cơ chế nội tỉnh để ánh xạ kết quả từ cơ sở dữ liệu sang đối tượng Java.
  2. Tiến Trình Tự Động Hóa: JSON libraries như Jackson, Gson dùng nội tỉnh để chuyển đổi đối tượng thành chuỗi JSON.
  3. Công Cụ Chung: Các công cụ xử lý thuộc tính phổ quát như BoUtils.getPropertyType.
  4. Xây Dựng Giao Diện Người Dùng: IDEs như IntelliJ IDEA, Eclipse dùng nội tỉnh để hiển thị và chỉnh sửa thuộc tính của đối tượng.

Thẻ: JavaBeans introspection PropertyDescriptor Reflection

Đăng vào ngày 9 tháng 6 lúc 23:54