2013-01-16 46 views

Trả lời

8

Phản ánh là một cấu trúc mạnh mẽ thường được sử dụng bởi các thư viện cơ bản như Guice và Hibernate để làm cho cuộc sống dễ dàng hơn. Nó thường được sử dụng khi một lớp cần được cấu hình và sau đó được khởi tạo ngay lập tức. Ví dụ:

public Strategy prepare(String clazz, Properties config) throws ClassNotFoundException, InstantiationException, IllegalAccessException { 
    Class<?> clazz = Class.forName(clazz); 
    Strategy strategy = (Strategy) clazz.newInstance(); 
    strategy.initialise(config); 
    return strategy; 
} 

Ở đây, thông số clazz đặt tên lớp là khởi tạo. Giả sử rằng lớp sẽ là một lớp con của lớp/giao diện Chiến lược. Sau đó nó cũng được khởi tạo với các thiết lập được truyền qua thông số cấu hình. Điều này cho phép một môi trường có khả năng cấu hình cao.

Tuy nhiên, phản ánh khá thường dẫn đến mã rất nguy hiểm (và độc hại) và vì lý do đó, nên tránh phản chiếu, trừ khi thật cần thiết. Cũng nên nhớ, phản xạ đó chậm hơn so với cuộc gọi trực tiếp. Đây là một ví dụ thực tế được lấy từ một hệ thống sản xuất về cách KHÔNG sử dụng sự phản chiếu.

private static CacheManager getRawInstance() { 
    lock.lock(); 
    try { 
     final Field field = CacheManager.class.getDeclaredField("singleton"); 
     field.setAccessible(true); // << -- ?? 
     return (CacheManager) field.get(CacheManager.class); 
    } catch (Exception e) { 
     logger.error(e.getMessage(), e); 
     return null; 
    } finally { 
     lock.unlock(); 
    } 
} 

Ở đây, trường riêng tư trong ehcache được thay đổi và truy cập. Đây là mã hóa hết sức xấu.

+1

Chờ đã, Field.setAccessible (true) được sử dụng trong sản xuất? ?? Tôi đoán đó là một ngày thú vị khi viên đá quý đó được tìm thấy. – Dan

+0

Vâng Dan, quả thật vậy ... cái khóa cũng đánh bóng đá quý hơn một chút (những gì đã xảy ra với "đồng bộ"?). Vấn đề được phát hiện khi ehcache bắt đầu hoạt động sai trong các phần khác của hệ thống (bỏ qua cấu hình, vv) Sau khi tính toán nó ... nó vẫn còn nguyên vẹn với một lời nhận xét như một lời cảnh báo. Đó là một bài học hay. Nó minh họa cách mã phản chiếu nguy hiểm có thể. –

1

TechExchange đã làm một công việc tuyệt vời giải thích phản ánh. Sự phản chiếu dường như là một con cừu đen trong Java. Tôi luôn luôn nghe mọi người nói rằng đó là lỗi của nó và dễ bị lỗi, nhưng tôi thấy nó khá ổn định và hiệu quả khi nó được thực hiện đúng. Tôi sẽ nói tránh sử dụng nó và thử một thư viện nội tâm bằng cách viết mã phản chiếu bản địa. Introspection cùng một điều như phản ánh, thường chỉ là một thư viện được xây dựng trên một thư viện phản ánh cơ bản. Spring và Apache-commons đều có các công cụ tuyệt vời, nếu bạn đang làm việc với bean.

Mùa xuân và Apache chỉ nhắm mục tiêu đến getters, thật không may, tôi không sống trong thế giới đậu. Một số đối tượng mà tôi phải làm việc là các phương thức Boolean 'là' và đã tìm thấy bản thân mình viết mã phản chiếu.

Dù sao ở đây là một số mã phản chiếu đơn giản lưu trữ mọi phương thức công khai với 0 đối số.

public void foo(final Class _class){ 
    List<Method> methods = new ArrayList<Method>(){{ 
     for(Method method : _class.getMethods()) { 

      if(Modifier.isPublic(method.getModifiers()) 
       && method.getGenericParameterTypes().length == 0){ 

      add(method); 
     } 
    }}; 
}