mardi 2 juin 2020

Is using method reference bad for performance?

I need to build my own library to handle events coming from an event bus, the first solution I came up with was an abstract class made like this one:

public abstract class MyEventListener<T> extends RealEventListener{
      private final Class<T> type; //the event class type
      private final String stream; //the stream 

      public abstract onEvent(T type); //the method my subclasses have to implement

      @Overrides
      public void onEvent(byte[] evt){ //takes the original, clunky method and evolves it with typing
          //convert and do stuff
          onEvent(convertedEvent); //call method
      }      
}

so, the classes only do:

@Component
public class Child extends MyEventListener<AType>{
    public Child(){
        super(AType.class, "stream"); //registers
     }

    @Overrides
    public void onMessage(AType evt){ //do stuff
}

I find this approach somewhat limiting and outdated (at least seeing the latest libraries). An example I can think of is that, this way, you are forced to handle separate events in separate classes.

So, I though of using annotations to have something like this:

@EventListener("stream") //1. you define the stream in this custom class annotation
public class Child {  //so no need to extend

   @ListenTo(type=AType.class) //2. you define the type on methods, this way a single class can handle more
   public void onMessage(AType event, //any other param){

   }

Now, for the magic behind, I though about using a startup annotation processing to retrieve the methods:

public void initialize(@EventListener List<Object> listeners) { //I inject all objects
    listeners.stream().map(..).collect(..) //use reflection to get all methods annotated with @ListenTo and put them inside of map <String, Method>

    eventBus.registerListener(new MyEventListener(methodMap)); //
}

Now, the listener will take somewhat the type from the original byte event and call the method:

String className = getClassFromEvent(evt);
listenerMap.get(className).invoke(evt);

According to you is this approach valid and, most importantly, efficient? Or, excluding the initialization phase, it could lead to performance problems at runtime? Of course I should make static checks at initialization to make sure that the annotated methods declare the event as parameter but it seems cleaner to me than the first one.





Aucun commentaire:

Enregistrer un commentaire