سؤال

في حين بسيطة واجهة يحركها إعلام الحدث الأطر جافا كانت موجودة منذ ما قبل الكمبري مرات (على سبيل المثالjava.الفاصوليا.PropertyChangeSupport) ، تزداد شعبية أطر استخدام الشرح يحركها إعلام الحدث بدلا من ذلك.

انظر على سبيل المثال JBossCache 2.2.المستمع فئة لديها المستمع أساليب المشروح ، بدلا من مطابقة جامدة واجهة.هذا هو أسهل بدلا من برنامج و أسهل للقراءة, منذ لم يكن لديك لكتابة فارغة تطبيقات المستمع الاسترجاعات التي كنت لا ترغب في (ونعم, أنا أعرف عن المستمع محول superclasses).

هنا عينة من JBossCache مستندات:

@CacheListener
public class MyListener {
   @CacheStarted
   @CacheStopped
   public void cacheStartStopEvent(Event e) {
         switch (e.getType()) {
            case Event.Type.CACHE_STARTED:
               System.out.println("Cache has started");
               break;    
            case Event.Type.CACHE_STOPPED:    
               System.out.println("Cache has stopped");
               break;    
         }
   }    

   @NodeCreated    
   @NodeRemoved
   @NodeVisited
   @NodeModified
   @NodeMoved
   public void logNodeEvent(NodeEvent ne) {
         log("An event on node " + ne.getFqn() + " has occured");
   }

}

المشكلة مع ذلك هو أنه أكثر من ذلك بكثير جدا من عملية المشاركة في كتابة الإطار إلى دعم هذا النوع من الشيء ، بسبب الشرح-انعكاس طبيعة ذلك.

لذا قبل أن تهمة قبالة الطريق من كتابة الإطار العام ، كنت آمل شخص قد فعلت ذلك بالفعل.وقد أي شخص يأتي عبر مثل هذا الشيء ؟

هل كانت مفيدة؟

المحلول

ويمكنك القيام بالفعل هذا اليوم مع EventBus .

وبعد مثال على ذلك هو من EventBus دليل الخطوات الأولى . شريط الحالة يقوم بتحديث استنادا إلى الأحداث المنشورة، وهناك حاجة لتسجيل تحكم شريط الحالة / القطعة كما المستمع من الناشر (ق). دون EventBus، سوف تحتاج إلى إضافة كما المستمع إلى العديد من الفئات شريط الحالة. كما يمكن إنشاء شريط الحالة ودمرت في أي وقت.

public StatusBar extends JLabel {
    public StatusBar() {
        AnnotationProcessor.process(this);
    }
    @EventSubscriber(eventClass=StatusEvent.class)
    public void updateStatus(StatusEvent statusEvent) {
        this.setText(statusEvent.getStatusText();
    }
}

وهناك مشروع مماثل ELF (الإطار المستمع الأحداث) ولكن يبدو أن يكون أقل نضجا.

وأنا تبحث حاليا عن الأطر إعلام الحدث على <لأ href = "http://spring-java-ee.blogspot.com/2009/12/publish-subscribe-event-driven.html" يختلط = "noreferrer "> نشر-الاشتراك الحدث مدفوعة البرمجة | الربيع كيلو في مقابل جافا EE ديف والمواد المتابعة.

نصائح أخرى

ولقد قدمت http://neoevents.googlecode.com للتعامل مع هذا النوع من الأحداث الشرح تستند معالج.

        @actionPerformed
        private void onClick() {
                //do something
        }

        protected void initComponents() {
                JButton button = new JButton("Click me!!!");
                button.addActionListener(new ActionListener(this) );
        }

ويبدو بهذه البساطة كنت أتوقع لها أن تكون. هي متاحة لكل مستمع واحد في J2SE شروحه.

لا خطأ تعقيدا بالنسبة ذكي.يبدو لي أن هذا من شأنه أن يكون:

  1. كابوس التصحيح
  2. من الصعب متابعة (من الصيانة المنظور ، أو أي شخص يحاول تغيير شيء 6 أشهر أسفل الخط)
  3. كامل if (event instanceof NodeCreatedEvent) مثل رمز.لماذا هذا أفضل من subclassing أحد adapter ليس لدي أي فكرة!

والمشكلة الرئيسية أرى هنا هي معلمات الأسلوب، التي تحد من الأساليب التي يمكن استخدامها فعليا التي الأحداث، وليس هناك وقت الترجمة مساعدة لذلك.

وهذا ما يجعل واجهات جذابة بالنسبة لي لتطبيقات نمط مراقب مثل نموذج الحدث جافا. أدوات مثل الكسوف يمكن اوتوغن بذرة طريقة لذلك لا يمكنك الحصول على توقيعات الخطأ. في المثال الخاص بك، فإنه من السهل جدا للاستخدام نوع المعلمة خطأ ولا تعرف حتى حدوث حدث (والذي قد يكون حالة الخطأ عدة أشهر أسفل الخط)

وشيء واحد كنت قد تحاول هي بلدي الشروح ومعالج لتنفيذ المراقبين وتطبيقات الكائن فارغة. افترض أن لديك

package a.b.c;

public interface SomeListener {
    void fee();
    void fie();
    void fo();
    void fum();
}

ووأراد أن إنشاء مثيل المستمع. هل يمكن أن يكتب

package x.y.z;

import a.b.c.SomeListener;
import com.javadude.annotation.Bean;
import com.javadude.annotation.NullObject;

@Bean(nullObjectImplementations = {@NullObject(type = SomeListener.class) })
public class Foo extends FooGen implements SomeListener {
    @Override
    public void fie() {
        // whatever code you need here
    }
}

لإنشاء مصدر لهذه الأحداث، يمكنك كتابة

package a.b.c;

import com.javadude.annotation.Bean;
import com.javadude.annotation.Observer;

@Bean(observers = {@Observer(type = SomeListener.class)})
public class Source extends SourceGen {
    // SourceGen will have add/remove listener and fire methods
    //   for each method in SomeListener
}

http://code.google.com/p/javadude/wiki/ شروح إذا كنت مهتما. قد تعطيك بعض الأفكار الأخرى كذلك.

جوجل الجوافة V11 قد أضاف إلى <لأ href = "HTTP: // code.google.com/p/guava-libraries/wiki/EventBusExplained "يختلط =" نوفولو "> عنصر EventBus يستخدم هذا النمط . أيضا يشرحون لماذا قرروا استخدام شروح بدلا من واجهات .

ولقد تم التفكير في إطار الحدث يحركها الشرح عام أيضا. أنا أحب الفوائد التي توفرها الكتابة ثابتة، ولكن نموذج الحدث يحركها واجهة الحالي هو مؤلم أن استخدام (رمز قبيح). سيكون من الممكن استخدام معالج الشرح مخصص للقيام ببعض الترجمة لمرة والتدقيق؟ قد تساعد على إضافة بعض "سلامة" في عداد المفقودين بعد أن قمنا جميع اعتادوا على.

ويمكن أيضا أن يتم ذلك وهناك الكثير من التحقق من الخطأ في الوقت الذي المستمعين و"مسجلة" مع المنتجين الحدث. وبالتالي، فإن فشل التطبيق المبكر (عندما يتم تسجيل المستمعين)، وربما حتى في عند بدء التشغيل في الوقت المحدد.

وهنا مثال على ما إطار عام لقد تم اللعب مع قد تبدو:

public class ExampleProducer {

    private EventSupport<ActionEvent> eventSupport;

    public ExampleProducer() {
        eventSupport = new EventSupport<ActionEvent>(this);
    }

    @AddListenersFor(ActionEvent.class)
    public void addActionListener(Object listener)
    {
        eventSupport.addListener(listener);
    }

    @RemoveListenersFor(ActionEvent.class)
    public void removeActionListener(Object listener)
    {
        eventSupport.removeListener(listener);
    }

    public void buttonClicked() {
        eventSupport.fire(new ActionEvent(this, 
                              ActionEvent.ACTION_PERFORMED, "Click"));
    }
   }

وومنتج يستخدم EventSupport، والذي يستخدم انعكاس لاستدعاء الأحداث. كما ذكرت من قبل، يمكن أن EventSupport التشكيل بعض الفحوص الأولية عندما يتم تسجيل المستمعين الأحداث.

public class ExampleListener
{   
  private ExampleProducer submitButton;

  public ExampleListener()
  {
    submitButton = new ExampleProducer();
    EventSupport.autoRegisterEvents(this);
  }

  @HandlesEventFor("submitButton")
  public void handleSubmitButtonClick(ActionEvent event)
  {
    //...some code to handle the event here
  }
}

وهنا، EventSupport لديه أسلوب ثابت يستخدم انعكاس لصناعة السيارات في تسجيل المستمع مع المنتج الحدث. هذا يلغي الحاجة إلى التسجيل يدويا مع مصدر الحدث. يمكن أن تستخدم معالج الشرح مخصص للتحقق من أن الشرح @HandlesEventFor يشير إلى حقل الفعلي للExampleListener. المعالج الشرح يمكن أن تفعله الشيكات الأخرى أيضا، مثل التأكد من أن معالج الحدث طريقة التوقيع مباريات مع واحدة من أساليب التسجيل في ExampleProducer (أساسا، وهو نفس الاختيار التي يمكن أن يؤديها في تسجيل الوقت).

ما رأيك؟ هل هذا يستحق وضع بعض الوقت في تطوير كامل؟

وهنا مشروع مماثل يسمى SJES .

public class SomeController {

private Calculator c1 = new Calculator();
private Calculator c2 = new Calculator();

public SomeController() {
    c1.registerReceiver(this);
    c2.registerReceiver(this);
    c1.add(10, 10);
    c2.add(20, 20);
}

@EventReceiver(handleFor="c1")
public void onResultC1(Calculator.Event e) {
    System.out.println("Calculator 1 got: " + e.result);
}

@EventReceiver(handleFor="c2")
public void onResultC2(Calculator.Event e) {
    System.out.println("Calculator 2 got: " + e.result);
}

@EventReceiver
public void onResultAll(Calculator.Event e) {
    System.out.println("Calculator got: " + e.result);
}
}

public class Calculator {

private EventHelper eventHelper = new EventHelper(this);

public class Event {

    long result;

    public Event(long result) {
        this.result = result;
    }
}

public class AddEvent extends Event {

    public AddEvent(long result) {
        super(result);
    }
}

public class SubEvent extends Event {

    public SubEvent(long result) {
        super(result);
    }
}

public void unregisterReceiver(Object o) {
    eventHelper.unregisterReceiver(o);
}

public void registerReceiver(Object o) {
    eventHelper.registerReceiver(o);
}

public void add(long a, long b) {
    eventHelper.fireEvent(new AddEvent(a + b));
}

public void sub(long a, long b) {
    eventHelper.fireEvent(new SubEvent(a - b));
}

public void pass(long a) {
    eventHelper.fireEvent(new Event(a));
}
}

وأعتقد أن هذا هو سهل جدا للاستخدام.

ويمكنك أيضا إجراء فحص MBassador مدفوعة ومن الشرح، جدا وخفيفة الوزن، ويستخدم الإشارات الضعيفة ( وبالتالي من السهل الاندماج في البيئات التي يتم الكائنات إدارة دورة حياة بإطار مثل الربيع أو guice أو على somethign).

وويوفر آلية الترشيح الكائن (وبالتالي هل يمكن الاشتراك في NodeEvent ونعلق بعض المرشحات لتقييد التعامل مع لمجموعة من أنواع معينة فقط الرسالة). يمكنك أيضا تحديد الشروح الخاصة بك لإعلان مخصصة من معالجات الخاصة بك.

وانها سريعة جدا والكفء للموارد. تحقق من هذه القياسي يظهر الرسم البياني أداء لسيناريوهات مختلفة باستخدام الجوافة أو mbassador.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top