2009-06-28 25 views
25

Có thể trong Java đơn giản để ghi đè lên một phương thức của một lớp học lập trình khi chạy (hoặc thậm chí tạo một phương thức mới)?Phản ánh Java: Làm cách nào để ghi đè hoặc tạo phương thức trong thời gian chạy?

Tôi muốn có thể thực hiện việc này ngay cả khi tôi không biết các lớp lúc biên dịch.

Những gì tôi có nghĩa là chính xác bằng cách ghi đè khi chạy:

abstract class MyClass{ 
    public void myMethod(); 
} 

class Overrider extends MyClass{ 
    @Override 
    public void myMethod(){} 
} 

class Injector{ 
    public static void myMethod(){ // STATIC !!! 
    // do actual stuff 
    } 
} 

// some magic code goes here 
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class); 

Bây giờ, gọi này ...

altered.myMethod(); 

... sẽ gọi Injector.myMethod() thay vì Overrider .myMethod().

Injector.myMethod() là tĩnh, bởi vì, sau khi làm "kỳ diệu" nó được gọi từ dụ lớp khác nhau (đó là Overrider), (vì vậy chúng tôi ngăn chặn nó từ truy cập vào các lĩnh vực địa phương).

+1

Bạn có thể cho chúng tôi biết bạn muốn ghi đè loại đối tượng nào không? Trong nháy mắt thứ hai, vấn đề của bạn nhắc tôi về mục tiêu của mô hình tiêm phụ thuộc. – akarnokd

Trả lời

10

Bạn có thể sử dụng giống như cglib cho tạo mã on-the-fly

8

Đối với giao diện có java.lang.reflect.Proxy.

Đối với các lớp học, bạn sẽ cần thư viện của bên thứ ba hoặc viết một đoạn mã công bằng. Nói chung tạo động các lớp theo cách này là tạo ra các mocks để thử nghiệm.

Ngoài ra còn có API thiết bị đo đạc cho phép sửa đổi các lớp học. Bạn cũng có thể sửa đổi các lớp với trình nạp lớp tùy chỉnh hoặc chỉ các tệp lớp trên đĩa.

+0

@ T.H.t: Theo ý kiến ​​của bạn, liệu AOP hay BCEL sẽ được áp dụng lại trong trường hợp này?Tôi đang phải đối mặt với một vấn đề tương tự hiện tại và không thể quyết định những gì để sử dụng. – akarnokd

+1

AOP rất chung chung. Tôi thích ASM hơn cho BCEL. oxbow_lakes đề cập đến cglib, mà tôi không thể nhớ tên của (và đã không được sử dụng). –

0

Nếu tôi đã làm đúng, vấn đề chính mà bạn quan tâm là làm thế nào để vượt qua một phương pháp đại biểu tĩnh (như trong C#), thông qua thể hiện phương thức giao diện.

Bạn có thể kiểm tra bài viết này: A Java Programmer Looks at C# Delegates, trong đó cho bạn thấy làm thế nào để có được một tham chiếu đến phương pháp tĩnh của bạn và gọi nó. Sau đó bạn có thể tạo một lớp bao bọc chấp nhận tên phương thức tĩnh trong hàm tạo của nó và thực hiện lớp cơ sở của bạn để gọi phương thức tĩnh từ phương thức cá thể.

8

Tôi đã viết một article for java.net về cách minh bạch thêm các câu lệnh ghi vào lớp khi nó được tải bởi trình nạp lớp bằng cách sử dụng tác nhân java.

Nó sử dụng thư viện Javassist để thao tác mã byte, bao gồm sử dụng trình biên dịch Javassist để tạo thêm bytecode, sau đó được chèn vào vị trí thích hợp và sau đó lớp kết quả được cung cấp cho trình nạp lớp.

Phiên bản tinh tế có sẵn với dự án slf4j.

+0

Bây giờ vài năm sau, tôi sẽ không đề nghị phương pháp này. Nếu bạn thực sự cần điều này, hãy xem xét Lập trình hướng Aspect. –

9

Trong java6 đã được thêm khả năng chuyển đổi bất kỳ lớp nào đã được tải. Hãy xem changes trong gói java.lang.instrument

+0

Tôi thậm chí quên rằng gói này tồn tại! Cảm ơn! –

Các vấn đề liên quan