2012-04-18 36 views
31

Tôi muốn tạo chú thích tùy chỉnh của riêng mình. Khung của tôi là ứng dụng java độc lập. Khi ai đó chú thích lớp pojo của mình, một mã "ẩn" đằng sau sẽ kích hoạt các phương thức.Cách tạo chú thích tùy chỉnh có mã đằng sau

Ví dụ: hôm nay trong Java EE, chúng tôi có chú thích @MessageDriven. Và khi bạn chú thích lớp học của mình với @MessageDriven và ngoài ra, hãy triển khai Giao diện MessageListener có một mã phía sau sẽ kích hoạt onMessage(Message msg). khi một tin nhắn đến từ một Hàng đợi/Chủ đề.

Tôi làm cách nào để tạo chú thích (@MyMessageDriven) có thể được thêm vào một bài hát và cũng có thể thực hiện MyCustomMessageListener.

Kết quả mà tôi mong muốn là kích hoạt mã "ẩn" (của tôi) sẽ kích hoạt phương thức của giao diện được triển khai (chính xác như nó hoạt động với mẫu tôi đã viết bên dưới).

+0

Bạn đang sử dụng khung công việc hoặc khung kinh doanh nào? – nobeh

+0

Đây là ứng dụng java độc lập. – rayman

Trả lời

31

Tôi khuyên bạn nên đọc this blog entry (snapshot on archive.org) cho đến khi tác giả nhớ (các) anh ấy có quyền truy cập vào tính năng quét thành phần của Spring.

Vấn đề ban đầu là quét đường dẫn lớp để tìm các lớp học bằng chú thích tùy chỉnh. Một khi điều này được thực hiện, bạn có các đối tượng trong ứng dụng độc lập của bạn thông qua đó sử dụng object.getClass().getAnnotations(), sau đó bạn có thể tiêm người nghe hoặc hành vi tùy chỉnh mà bạn cần thêm vào đối tượng đang giữ chú thích tùy chỉnh.

Hãy nói rằng bạn có chú thích tùy chỉnh sau:

@Target({ ElementType.TYPE }) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyMessageDriven {} 

Và bạn sử dụng nó một số lớp trong bạn ứng dụng:

@MyMessageDriven 
public class MyObject {} 

Bây giờ, ở vị trí thích hợp trong ứng dụng của bạn, bạn nên có một phương pháp để đưa ra tất cả các lớp mang MyMessageDriven:

Set<Class<?>> findAllMessageDrivenClasses() { 
    final StopWatch sw = new StopWatch(); 
    sw.start(); 
    final Reflections reflections = new Reflections("org.projectx", new TypeAnnotationsScanner()); 
    Set<Class<?>> allMessageDrivens = reflections.getTypesAnnotatedWith(MyMessageDriven.class); // NOTE HERE 
    sw.stop(); 
    return allMessageDrivens; 
} 

Có điều này, tôi giả định rằng có một điểm trong ứng dụng của bạn là (1) bạn có quyền truy cập vào các đối tượng trong ứng dụng của bạn, hoặc (2) có mô hình khách truy cập hoặc trình lặp trên tất cả các đối tượng trong ứng dụng. Vì vậy, trong một lúc nào đó, tôi cho rằng chúng tôi có tất cả các đối tượng mục tiêu như objects:

Set<Class<?>> msgDrivenClasses = findAllMessageDrivenClasses(); 
for (Object o : objects) { 
    if (msgDrivenClasses.contains(o.getClass()) { 
    invokeTheMessageListener(o); 
    } 
} 

Mặt khác, cần có một số thực hiện MyMessageListener có sẵn khi các đối tượng có MyMessageDriven được tìm thấy:

void invokeTheMessageListener(Object o) { 
    theMessageListener.onMessage(o); 
} 

Câu trả lời này được điều chỉnh từ mục nhập blog, vì vậy vui lòng tham khảo blog để biết cấu hình thư viện. Và, cuối cùng nhưng không kém phần quan trọng, đây là một mã mẫu cho vấn đề và nó có thể được cấu trúc lại thành kiểu tương thích và thanh lịch hơn.

Cập nhật: Có yêu cầu đối tượng được nhắm mục tiêu cần lưu ý đến người nghe của riêng họ. Vì vậy, tôi đề nghị cách tiếp cận sau đây.Chúng ta hãy có một giao diện MyMessageListenerAware:

interface MyMessageListenerAware { 
    MyMessageListener getMyMessageListener(); 
} 

// and this is the original MyMessageListener 
interface MyMessageListener { 
    void onMessage(Object o); 
} 

Bây giờ, các đối tượng mục tiêu cần thực hiện các giao diện trên:

class MySampleObject implements MyMessageListenerAware { 

    public MyMesssageListener getMyMessageLisener() { 
    return mySampleObjectImplementationOfMyMessageListener; 
    } 

} 

Có điều này, phương pháp invokeTheMessageListener trở thành như:

void invokeMessageListener(Object o) { 
    if (o instance MyMessageListenerAware) { 
    MyMessageListener l = ((MyMessageListenerAware) o).getMyMessageListener(); 
    l.onMessage(o); 
    } 
} 

Mặc dù , Tôi khuyên bạn nên đọc về mô hình Visitor hoặc Strategy. Những gì bạn muốn làm dường như với tôi như bạn cần một số đối tượng phản ứng/hành động/quy trình cho một đối tượng/sự kiện phổ biến trong ứng dụng nhưng mỗi với giải thích/thuật toán/triển khai của riêng họ.

+0

Xin chào, nhưng tôi không sử dụng Spring. – rayman

+0

Tôi đã đề cập đến "lên đến điểm". Mùa xuân chỉ là nếu bạn có mùa xuân khác hơn là nó vẫn còn đầy đủ. – nobeh

+0

Có chính xác tôi muốn đưa người nghe đến đối tượng nhưng thật khó để tôi hiểu cách thực hiện nó từ ví dụ Mùa xuân của bạn. có lẽ bạn có tài liệu tham khảo khác cho tôi? cảm ơn! – rayman

9

tạo ra một cái gì đó chú thích như thế này:

public @interface MyMessageDriven{ 
} 

Và bạn có một giao diện mà có thể áp dụng chú thích như thế này:

public interface MyMessagListener { 

    public void message(); 
} 



@MyMessageDriven 
public class MyMessage implements MyMessagListener { 
    public void message(){ 
    System.out.println(" I am executed") 
    } 
} 

tải lớp trên sử dụng classloader và sử dụng phản xạ kiểm tra các chú thích là presrent.

nếu có, hãy sử dụng thể hiện được tải để thực thi nó.

Object obj = ClassLoader.getSystemClassLoader().loadClass("MyMessage").newInstance(); 
    MyMessagListener mml = (MyMessagListener) obj; 
    mml.message(); 

Trình thực hiện trình lắng nghe bạn có thể đặt trong lớp MyMessage hoặc một số lớp khác triển khai MessageListener.

Trong trường hợp này, cần cung cấp triển khai cho message() những gì nó sẽ làm.

Nhưng lớp này nên được tải và điều quan trọng hơn ở đây là cách lớp MyMessage của bạn được tải.

Điều đó dựa trên dữ liệu meta có trong lớp MyMessage. Tương tự, trong kịch bản thời gian thực, đây là cách hoạt động của nó.

Chú thích là siêu dữ liệu cho lớp dựa trên dữ liệu được cung cấp, hãy thực hiện điều gì đó.Hãy siêu dữ liệu này không có trong lớp MyMessage, bạn không cần thực hiện phương thức message().

Hy vọng điều này sẽ giúp bạn.

+0

Xin chào, Nhưng có hai điều: tôi nên đặt triển khai người nghe của mình ở đâu? và làm thế nào để tiêm nó vào lớp MyMessage. thứ hai khi/nơi nào tôi cần phải sử dụng mã thực thi bạn đã viết dưới đây? – rayman

+0

Tôi đã cập nhật câu trả lời – UVM

+0

Trong MDB bình thường, chúng tôi đang thực hiện một số logic nghiệp vụ, phải.Được thực thi tự động.Điều này xảy ra như thế nào là MDB của bạn được tải.2. Khi nó được tải, hãy kiểm tra xem chú thích có hiện diện hay không.3. Nếu chú thích là hiện tại, bạn cast lớp nạp này vào giao diện MyMessageListener.Đó là mã tôi đã chỉ ra cho bạn. Nhưng hãy nhớ rằng tất cả các cơ chế này đang xảy ra bên trong khung công tác trừu tượng. Tôi đang nói rằng kịch bản chỉ.4.Bây giờ khuôn khổ, đang làm một số hoạt động như, nhận được tin nhắn từ hàng đợi hoặc làm một số hoạt động.5. Sau đó, nó được gọi là phương thức messagelistener.message(). – UVM

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