2012-04-18 23 views
11

Tôi đang viết một công cụ/thư viện trò chơi, trong đó tôi có một lớp điều phối sự kiện gửi các sự kiện bằng cách gọi các phương thức nghe của các lớp xử lý sự kiện "đã đăng ký". Người ta có thể đăng ký một trình xử lý sự kiện/người nghe với người điều phối sự kiện bằng cách gọi phương thức điều phối thích hợp. Điều này rõ ràng dẫn đến một số mã boilerplate để đăng ký mọi xử lý sự kiện (và các khía cạnh khác của động cơ của tôi có mã bolierplate tương tự), vì vậy tôi đã tự hỏi - làm thế nào về việc sử dụng Instrumentation để thêm vào tất cả các mã cần thiết trong khi tải của lớp xử lý sự kiện, do đó không đăng ký rõ ràng với trình điều phối sự kiện là cần thiết trong khi mã hóa - cuộc gọi đến phương thức đăng ký của điều phối viên được thêm tự động khi chương trình được chạy.Thêm mã vào một lớp Java w/Thiết bị đo đạc: ASM hoặc BCEL?

Đó là sự hiểu biết của tôi rằng để sử dụng Thiết bị đo đạc nên sử dụng một số API bổ trợ bytecode. Tôi biết hai - ASM và BCEL. Tôi nên sử dụng cái nào? Rõ ràng, đây là một nhiệm vụ hơi đơn giản mà tôi đang cố gắng làm, vì vậy tôi muốn một công việc dễ học và tài liệu tốt hơn.

EDIT: Đây là một ví dụ cụ thể.

gốc lớp xử lý sự kiện:

@Handler //indicates this this class should be transformed 
public class MouseEventHandler implements EventHandler<MouseEvent> 
{ 
    //hidden default constructor 
    public void handleEvent(MouseEvent event) 
    { ... } 
} 

Sau khi chuyển đổi:

@Handler 
public class MouseEventHandler implements EventHandler<MouseEvent> 
{ 
    public MouseEventHandler() 
    { 
     //add this line of code to default constructor 
     Game.getEventDispatcher().addEventHandler(this); 
    } 
    public void handleEvent(MouseEvent event) 
    { ... } 
} 

Trả lời

20

Tuy nhiên, tôi sẽ xem xét các tùy chọn khác trước khi nhảy vào thao tác bytecode.

+0

bcel đã được đưa vào JDK –

+1

@ alexander.box: Có, là phụ thuộc vào XSLTC biến Xalan, nhưng nó không phải là API chuẩn và cũng bị ẩn trong gói com.sun.org.apache.bcel.internal ! Tốt hơn cung cấp bình của riêng bạn. – Daniel

+2

Ồ, và trong khi tôi đang ở đó: ASM là một lựa chọn rất tốt khi các lớp học phải được thiết kế. Dễ hiểu và sử dụng. Ngoài ra nó có một tài liệu rất tốt đẹp. – Daniel

6

Việc thêm logic vào một vài lớp có thể nhàm chán, nhưng trừ khi bạn có hàng nghìn bộ xử lý, đó là cách tôi sẽ thực hiện. Giữ đơn giản.

Điều đó nói rằng,

Game.registerHandler(this); 

sẽ có nhiều hướng đối tượng.

Cách thay thế để thêm logic trong mỗi lớp là giới thiệu nhà máy có trách nhiệm khởi tạo trình xử lý.

HandlerFactory.createMouseHandler(); 

Và phương pháp createMouseHandler chứa một cái gì đó giống như

Handler mh = new MousheHandler(); 
registerHandler(mh); 
return mh; 

Nếu bạn không muốn một trong những lựa chọn, tôi sẽ xem xét một trong hai khung khía cạnh (có thể AspectJ) hoặc một container cho invertion Kiểm soát (có thể là Spring IoC). Các khía cạnh cho phép bạn chú thích nguồn của bạn và mã "dệt" tại các địa điểm đã chọn. Vùng chứa IoC cho phép bạn kiểm soát vòng đời của đối tượng (ví dụ: instantiation). Cả hai đều sử dụng thiết bị bytecode phía sau khung cảnh.

Nhưng nếu bạn muốn tự mình làm thiết bị đo đạc, tôi chỉ có thể so sánh Javassist và ASM mà tôi đã sử dụng một cách cá nhân.

ASM là cấp thấp và hoạt động thực sự ở cấp độ bytecode java. Bạn phải làm quen với nó. Khuôn khổ được thiết kế rất tốt, hướng dẫn sử dụng rất tuyệt vời và nó là một thư viện tuyệt vời. Một mặt, nó có thể phức tạp để thay thế các mẫu mã bytecode, bởi vì nó đòi hỏi một sự chuyển đổi "trạng thái" được gọi là. Một mặt khác, bạn có toàn quyền kiểm soát bytecode.

Javassist cao cấp hơn. Bạn không hoạt động ở cấp độ nguyên bản của bytecode, mức cao hơn một chút, ví dụ: các trường đọc/ghi, gửi tin nhắn, xây dựng. Ngoài ra, nó cho phép bạn chỉ định các thay đổi bằng cách sử dụng cú pháp java thông thường, sau đó được biên dịch bởi khung công tác. API là một chút bối rối, bởi vì dự án đã phát triển qua nhiều năm. Có tài liệu về khuôn khổ, nhưng không tập trung tốt như ASM.