2012-12-28 6 views
5

Tôi nghĩ rằng tôi đã hiểu CDI hoạt động như thế nào và để lặn sâu vào nó, tôi muốn thử sử dụng nó với một ví dụ thế giới thực. Tôi bị mắc kẹt với một điều mà tôi cần sự giúp đỡ của bạn để làm cho tôi hiểu. Tôi thực sự đánh giá cao sự giúp đỡ của bạn về vấn đề này.Phương pháp CDI @Producer có thể lấy thông số tùy chỉnh không?

Tôi có khung công việc riêng được phát triển bằng cách sử dụng API phản chiếu Java và cấu hình XML, dựa trên loại "nguồn" và "eventName" cụ thể mà tôi tải lớp Mô-đun thích hợp và gọi phương thức "xử lý" trên đó. Mọi thứ đều hoạt động tốt trong dự án của chúng tôi.

tôi đã hào hứng với tính năng CDI và muốn để cho nó thử với khuôn khổ công việc mà tôi đang lên kế hoạch tiêm lớp Mô-đun thay vì tải chúng bằng cách sử Reflection vv ...

Chỉ cần để cung cấp cho bạn một ý tưởng, tôi sẽ cố gắng để giữ mọi thứ đơn giản ở đây.

"Message.java" là một loại đối tượng chuyển chứa "Nguồn" và "eventName", để chúng tôi có thể tải mô-đun phù hợp.

public class Message{ 
private String source; 
private String eventName; 
} 

cấu hình mô-đun như sau

<modules> 
<module> 
    <source>A</source> 
    <eventName>validate</eventName> 
    <moduleClass>ValidatorModule</moduleClass> 
</module> 
<module> 
    <source>B</source> 
    <eventName>generate</eventName> 
    <moduleClass>GeneratorModule</moduleClass> 
</module> 
</modules> 

ModuleLoader.java

public class ModuleLoader { 
public void loadAndProcess(Message message){ 
    String source=message.getSource(); 
    String eventName=message.getEventName(); 

    //Load Module based on above values. 

} 
} 

Câu hỏi

Bây giờ, nếu tôi muốn thực hiện cùng qua CDI để tiêm cho tôi một Module (trong lớp ModuleLoader), tôi có thể viết lớp Nhà máy bằng phương pháp @Produce, có thể làm điều đó. NHƯNG câu hỏi của tôi là,

a) cách có thể chuyển đối tượng thư đến phương pháp @Produce để tra cứu dựa trên eventName và nguồn?

Bạn có thể vui lòng cung cấp cho tôi đề xuất không?

Xin cảm ơn trước.

Trả lời

4

Cái này hơi phức tạp vì CDI không hoạt động theo cách tương tự như giải pháp tùy chỉnh của bạn (nếu tôi hiểu chính xác). CDI phải có tất cả danh sách các phụ thuộc và độ phân giải cho những phụ thuộc đó vào thời gian khởi động, nơi mà giải pháp của bạn có vẻ như nó tìm thấy mọi thứ trong thời gian chạy, nơi mọi thứ có thể thay đổi. Điều đó đang được nói có một vài điều bạn có thể thử.

Bạn có thể thử tiêm một số InjectionPoint làm tham số cho phương thức sản xuất và trả về đúng đối tượng hoặc tạo đúng loại.

Ngoài ra còn tạo ra phần mở rộng của riêng bạn để làm điều này và tạo ra phụ thuộc và hệ thống dây điện cho họ tất cả lên trong phần mở rộng (hãy nhìn vào ProcessInjectionTarget, ProcessAnnotatedType, và 'AfterBeanDiscovery` sự kiện. Những twoquickstarts cũng có thể giúp có được một số ý tưởng đi.

+0

Xin lưu ý rằng mẹo InjectionPoint chỉ hoạt động nếu bạn @Sản xuất một bean phụ thuộc phạm vi. Đối với đậu bình thường (SessionScoped, ApplicationScoped, RequestScoped, vv) nó sẽ _not_ làm việc khi bạn có nhiều điểm tiêm và không chỉ là một điểm duy nhất. – struberg

3

Tôi nghĩ bạn có thể đang đi sai đường dẫn về nhà sản xuất. Thay vào đó, sẽ tốt hơn nếu sử dụng một người quan sát đặc biệt dựa trên những gì bạn đã mô tả.

Tôi đang giả định rằng đối tượng truyền "Message" được sử dụng trừu tượng như một sự kiện hệ thống rộng lớn nơi bạn kích hoạt sự kiện đó và bạn muốn một số trình xử lý được xác định trong khung XML của mình. người quản lý cho sự kiện, khởi tạo nó (nếu cần), và sau đó gọi lớp đó qua sự kiện đó.


@ApplicationScoped 
public class MyMessageObserver { 

    public void handleMessageEvent(@Observes Message message) { 
     //Load Module based on above values and process the event 
    } 
} 

Bây giờ chúng ta hãy giả sử bạn muốn sử dụng giao diện ban đầu của bạn (tôi sẽ đoán nó trông giống như):


public interface IMessageHandler { 
    public void handleMessage(final Message message); 
} 

@ApplicationScoped 
public class EventMessageHandler implements IMessageHandler { 

    @Inject 
    private Event<Message> messageEvent; 

    public void handleMessage(Message message) { 
     messageEvent.fire(message); 
    } 
} 

Sau đó, trong bất kỳ lớp kế thừa bạn muốn sử dụng nó: @Inject IMessageHandler handler;

Điều này sẽ cho phép bạn làm mọi thứ bạn đã mô tả.

+1

Cảm ơn bạn đã hiển thị một cách khác. Cách tiếp cận này dường như hứa hẹn. Tôi sẽ cho nó nó một cơ hội. – Raj

2

Có thể bạn cần somthing như thế:

  1. Bạn cần vòng loại. Chú thích như @Module, sẽ lấy hai tham số nguồn và eventName; Chúng phải là giá trị không đủ điều kiện. Xem tài liệu.

  2. Thứ hai bạn cần một nhà sản xuất:

    @Produces 
    @Module 
    public Module makeAmodule(InjectionPoint ip) { 
        // load the module, take source and eventName from ip 
    } 
    
  3. Tiêm ở vị trí thích hợp như thế:

    @Inject 
    @Module(source="A", eventName="validate") 
    Module modulA; 
    

Chỉ có một vấn đề với giải pháp đó, những mô-đun phải phụ thuộc phạm vi, nếu không hệ thống sẽ tiêm cùng một mối quan hệ mô-đun của nguồn và eventName. Nếu bạn muốn sử dụng phạm vi, sau đó bạn cần làm cho nguồn và EventName thông số có trình độ và:

  • làm cho một phần mở rộng cho CDI, đăng ký theo chương trình sản xuất
  • hoặc làm phương pháp sản xuất cho mỗi và mọi tổ hợp có thể có của nguồn và eventName (Tôi không nghĩ rằng nó là tốt đẹp)