Changed reflection to use (much faster) ReflectASM
This commit is contained in:
parent
2e7cc11799
commit
220e522ff0
|
@ -1,6 +1,6 @@
|
|||
package net.engio.mbassy.dispatch;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
|
||||
/**
|
||||
* A handler invocation encapsulates the logic that is used to invoke a single
|
||||
|
@ -28,7 +28,7 @@ public interface IHandlerInvocation {
|
|||
* type that the handler consumes
|
||||
* @param handler The handler (method) that will be called via reflection
|
||||
*/
|
||||
void invoke(Object listener, Method handler, Object message) throws Throwable;
|
||||
void invoke(Object listener, MethodAccess handler, int methodIndex, Object message) throws Throwable;
|
||||
|
||||
/**
|
||||
* Invoke the message delivery logic of this handler
|
||||
|
@ -39,7 +39,7 @@ public interface IHandlerInvocation {
|
|||
* type that the handler consumes
|
||||
* @param handler The handler (method) that will be called via reflection
|
||||
*/
|
||||
void invoke(Object listener, Method handler, Object message1, Object message2) throws Throwable;
|
||||
void invoke(Object listener, MethodAccess handler, int methodIndex, Object message1, Object message2) throws Throwable;
|
||||
|
||||
/**
|
||||
* Invoke the message delivery logic of this handler
|
||||
|
@ -50,7 +50,7 @@ public interface IHandlerInvocation {
|
|||
* type that the handler consumes
|
||||
* @param handler The handler (method) that will be called via reflection
|
||||
*/
|
||||
void invoke(Object listener, Method handler, Object message1, Object message2, Object message3) throws Throwable;
|
||||
void invoke(Object listener, MethodAccess handler, int methodIndex, Object message1, Object message2, Object message3) throws Throwable;
|
||||
|
||||
/**
|
||||
* Invoke the message delivery logic of this handler
|
||||
|
@ -61,5 +61,5 @@ public interface IHandlerInvocation {
|
|||
* type that the handler consumes
|
||||
* @param handler The handler (method) that will be called via reflection
|
||||
*/
|
||||
void invoke(Object listener, Method handler, Object... message) throws Throwable;
|
||||
void invoke(Object listener, MethodAccess handler, int methodIndex, Object... message) throws Throwable;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package net.engio.mbassy.dispatch;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
|
||||
/**
|
||||
* Uses reflection to invoke a message handler for a given message.
|
||||
|
@ -17,22 +17,22 @@ public class ReflectiveHandlerInvocation implements IHandlerInvocation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object message) throws Throwable {
|
||||
handler.invoke(listener, message);
|
||||
public void invoke(final Object listener, final MethodAccess handler, final int methodIndex, final Object message) throws Throwable {
|
||||
handler.invoke(listener, methodIndex, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object message1, final Object message2) throws Throwable {
|
||||
handler.invoke(listener, message1, message2);
|
||||
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2) throws Throwable {
|
||||
handler.invoke(listener, methodIndex, message1, message2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object message1, final Object message2, final Object message3) throws Throwable {
|
||||
handler.invoke(listener, message1, message2, message3);
|
||||
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2, final Object message3) throws Throwable {
|
||||
handler.invoke(listener, methodIndex, message1, message2, message3);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object... messages) throws Throwable {
|
||||
handler.invoke(listener, messages);
|
||||
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object... messages) throws Throwable {
|
||||
handler.invoke(listener, methodIndex, messages);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package net.engio.mbassy.dispatch;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
|
||||
/**
|
||||
* Synchronizes message handler invocations for all handlers that specify @Synchronized
|
||||
|
@ -19,30 +19,30 @@ public class SynchronizedHandlerInvocation implements IHandlerInvocation {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object message) throws Throwable {
|
||||
public void invoke(final Object listener, final MethodAccess handler, final int methodIndex, final Object message) throws Throwable {
|
||||
synchronized (listener) {
|
||||
this.delegate.invoke(listener, handler, message);
|
||||
this.delegate.invoke(listener, handler, methodIndex, message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object message1, final Object message2) throws Throwable {
|
||||
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2) throws Throwable {
|
||||
synchronized (listener) {
|
||||
this.delegate.invoke(listener, handler, message1, message2);
|
||||
this.delegate.invoke(listener, handler, methodIndex, message1, message2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object message1, final Object message2, final Object message3) throws Throwable {
|
||||
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object message1, final Object message2, final Object message3) throws Throwable {
|
||||
synchronized (listener) {
|
||||
this.delegate.invoke(listener, handler, message1, message2, message3);
|
||||
this.delegate.invoke(listener, handler, methodIndex, message1, message2, message3);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(final Object listener, Method handler, final Object... messages) throws Throwable {
|
||||
public void invoke(final Object listener, MethodAccess handler, int methodIndex, final Object... messages) throws Throwable {
|
||||
synchronized (listener) {
|
||||
this.delegate.invoke(listener, handler, messages);
|
||||
this.delegate.invoke(listener, handler, methodIndex, messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.engio.mbassy.error;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
|
@ -20,7 +19,7 @@ public class PublicationError {
|
|||
// Internal state
|
||||
private Throwable cause;
|
||||
private String message;
|
||||
private Method handler;
|
||||
private String methodName;
|
||||
private Object listener;
|
||||
private Object[] publishedObjects;
|
||||
|
||||
|
@ -59,12 +58,12 @@ public class PublicationError {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Method getHandler() {
|
||||
return this.handler;
|
||||
public String getMethodName() {
|
||||
return this.methodName;
|
||||
}
|
||||
|
||||
public PublicationError setHandler(Method handler) {
|
||||
this.handler = handler;
|
||||
public PublicationError setMethodName(String methodName) {
|
||||
this.methodName = methodName;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -122,7 +121,7 @@ public class PublicationError {
|
|||
newLine +
|
||||
"\tmessage='" + this.message + '\'' +
|
||||
newLine +
|
||||
"\thandler=" + this.handler +
|
||||
"\tmethod=" + this.methodName +
|
||||
newLine +
|
||||
"\tlistener=" + this.listener +
|
||||
newLine +
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package net.engio.mbassy.listener;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
@ -8,6 +7,8 @@ import net.engio.mbassy.annotations.Handler;
|
|||
import net.engio.mbassy.annotations.Synchronized;
|
||||
import net.engio.mbassy.common.ReflectionUtils;
|
||||
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
|
||||
/**
|
||||
* Any method in any class annotated with the @Handler annotation represents a message handler. The class that contains
|
||||
* the handler is called a message listener and more generally, any class containing a message handler in its class hierarchy
|
||||
|
@ -29,7 +30,8 @@ import net.engio.mbassy.common.ReflectionUtils;
|
|||
*/
|
||||
public class MessageHandler {
|
||||
|
||||
private final Method handler;
|
||||
private final MethodAccess handler;
|
||||
private final int methodIndex;
|
||||
private final Class<?>[] handledMessages;
|
||||
private final boolean acceptsSubtypes;
|
||||
private final MessageListener listenerConfig;
|
||||
|
@ -46,9 +48,10 @@ public class MessageHandler {
|
|||
}
|
||||
|
||||
Class<?>[] handledMessages = handler.getParameterTypes();
|
||||
handler.setAccessible(true);
|
||||
|
||||
this.handler = handler;
|
||||
this.handler = MethodAccess.get(handler.getDeclaringClass());
|
||||
this.methodIndex = this.handler.getIndex(handler.getName(), handledMessages);
|
||||
|
||||
this.acceptsSubtypes = !handlerConfig.rejectSubtypes();
|
||||
this.listenerConfig = listenerMetadata;
|
||||
this.isSynchronized = ReflectionUtils.getAnnotation(handler, Synchronized.class) != null;
|
||||
|
@ -59,10 +62,6 @@ public class MessageHandler {
|
|||
this.isVarArg = handledMessages.length == 1 && handledMessages[0].isArray();
|
||||
}
|
||||
|
||||
public <A extends Annotation> A getAnnotation(Class<A> annotationType){
|
||||
return ReflectionUtils.getAnnotation(this.handler,annotationType);
|
||||
}
|
||||
|
||||
public boolean isSynchronized(){
|
||||
return this.isSynchronized;
|
||||
}
|
||||
|
@ -71,10 +70,14 @@ public class MessageHandler {
|
|||
return this.listenerConfig.isFromListener(listener);
|
||||
}
|
||||
|
||||
public Method getHandler() {
|
||||
public MethodAccess getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
public int getMethodIndex() {
|
||||
return this.methodIndex;
|
||||
}
|
||||
|
||||
public Class<?>[] getHandledMessages() {
|
||||
return this.handledMessages;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package net.engio.mbassy.subscription;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.engio.mbassy.common.IConcurrentSet;
|
||||
|
@ -13,6 +12,8 @@ import net.engio.mbassy.error.ErrorHandlingSupport;
|
|||
import net.engio.mbassy.error.PublicationError;
|
||||
import net.engio.mbassy.listener.MessageHandler;
|
||||
|
||||
import com.esotericsoftware.reflectasm.MethodAccess;
|
||||
|
||||
/**
|
||||
* A subscription is a thread-safe container that manages exactly one message handler of all registered
|
||||
* message listeners of the same class, i.e. all subscribed instances (excluding subclasses) of a SingleMessageHandler.class
|
||||
|
@ -126,27 +127,18 @@ public class Subscription {
|
|||
|
||||
public void publishToSubscription(ErrorHandlingSupport errorHandler, Object message) {
|
||||
if (this.listeners.size() > 0) {
|
||||
|
||||
/**
|
||||
* Delivers the given message to the given set of listeners.
|
||||
* Delivery may be delayed, aborted or restricted in various ways, depending
|
||||
* on the configuration of the dispatcher
|
||||
*
|
||||
* @param publication The message publication that initiated the dispatch
|
||||
* @param message The message that should be delivered to the listeners
|
||||
* @param listeners The listeners that should receive the message
|
||||
*/
|
||||
Method handler = this.handlerMetadata.getHandler();
|
||||
MethodAccess handler = this.handlerMetadata.getHandler();
|
||||
int methodIndex = this.handlerMetadata.getMethodIndex();
|
||||
|
||||
for (Object listener : this.listeners) {
|
||||
try {
|
||||
this.invocation.invoke(listener, handler, message);
|
||||
this.invocation.invoke(listener, handler, methodIndex, message);
|
||||
} catch (IllegalAccessException e) {
|
||||
errorHandler.handlePublicationError(new PublicationError()
|
||||
.setMessage("Error during invocation of message handler. " +
|
||||
"The class or method is not accessible")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -155,7 +147,7 @@ public class Subscription {
|
|||
"Wrong arguments passed to method. Was: " + message.getClass()
|
||||
+ "Expected: " + handler.getParameterTypes()[0])
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message));
|
||||
} catch (InvocationTargetException e) {
|
||||
|
@ -163,7 +155,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"Message handler threw exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message));
|
||||
} catch (Throwable e) {
|
||||
|
@ -171,7 +163,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"The handler code threw an exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message));
|
||||
}
|
||||
|
@ -181,27 +173,18 @@ public class Subscription {
|
|||
|
||||
public void publishToSubscription(ErrorHandlingSupport errorHandler, Object message1, Object message2) {
|
||||
if (this.listeners.size() > 0) {
|
||||
|
||||
/**
|
||||
* Delivers the given message to the given set of listeners.
|
||||
* Delivery may be delayed, aborted or restricted in various ways, depending
|
||||
* on the configuration of the dispatcher
|
||||
*
|
||||
* @param publication The message publication that initiated the dispatch
|
||||
* @param message The message that should be delivered to the listeners
|
||||
* @param listeners The listeners that should receive the message
|
||||
*/
|
||||
Method handler = this.handlerMetadata.getHandler();
|
||||
MethodAccess handler = this.handlerMetadata.getHandler();
|
||||
int methodIndex = this.handlerMetadata.getMethodIndex();
|
||||
|
||||
for (Object listener : this.listeners) {
|
||||
try {
|
||||
this.invocation.invoke(listener, handler, message1, message2);
|
||||
this.invocation.invoke(listener, handler, methodIndex, message1, message2);
|
||||
} catch (IllegalAccessException e) {
|
||||
errorHandler.handlePublicationError(new PublicationError()
|
||||
.setMessage("Error during invocation of message handler. " +
|
||||
"The class or method is not accessible")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -214,7 +197,7 @@ public class Subscription {
|
|||
handler.getParameterTypes()[1]
|
||||
)
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2));
|
||||
} catch (InvocationTargetException e) {
|
||||
|
@ -222,7 +205,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"Message handler threw exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2));
|
||||
} catch (Throwable e) {
|
||||
|
@ -230,7 +213,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"The handler code threw an exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2));
|
||||
}
|
||||
|
@ -240,27 +223,18 @@ public class Subscription {
|
|||
|
||||
public void publishToSubscription(ErrorHandlingSupport errorHandler, Object message1, Object message2, Object message3) {
|
||||
if (this.listeners.size() > 0) {
|
||||
|
||||
/**
|
||||
* Delivers the given message to the given set of listeners.
|
||||
* Delivery may be delayed, aborted or restricted in various ways, depending
|
||||
* on the configuration of the dispatcher
|
||||
*
|
||||
* @param publication The message publication that initiated the dispatch
|
||||
* @param message The message that should be delivered to the listeners
|
||||
* @param listeners The listeners that should receive the message
|
||||
*/
|
||||
Method handler = this.handlerMetadata.getHandler();
|
||||
MethodAccess handler = this.handlerMetadata.getHandler();
|
||||
int methodIndex = this.handlerMetadata.getMethodIndex();
|
||||
|
||||
for (Object listener : this.listeners) {
|
||||
try {
|
||||
this.invocation.invoke(listener, handler, message1, message2, message3);
|
||||
this.invocation.invoke(listener, handler, methodIndex, message1, message2, message3);
|
||||
} catch (IllegalAccessException e) {
|
||||
errorHandler.handlePublicationError(new PublicationError()
|
||||
.setMessage("Error during invocation of message handler. " +
|
||||
"The class or method is not accessible")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -275,7 +249,7 @@ public class Subscription {
|
|||
handler.getParameterTypes()[2]
|
||||
)
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
} catch (InvocationTargetException e) {
|
||||
|
@ -283,7 +257,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"Message handler threw exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
} catch (Throwable e) {
|
||||
|
@ -291,7 +265,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"The handler code threw an exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(message1, message2, message3));
|
||||
}
|
||||
|
@ -301,27 +275,18 @@ public class Subscription {
|
|||
|
||||
public void publishToSubscription(ErrorHandlingSupport errorHandler, Object... messages) {
|
||||
if (this.listeners.size() > 0) {
|
||||
|
||||
/**
|
||||
* Delivers the given message to the given set of listeners.
|
||||
* Delivery may be delayed, aborted or restricted in various ways, depending
|
||||
* on the configuration of the dispatcher
|
||||
*
|
||||
* @param publication The message publication that initiated the dispatch
|
||||
* @param message The message that should be delivered to the listeners
|
||||
* @param listeners The listeners that should receive the message
|
||||
*/
|
||||
Method handler = this.handlerMetadata.getHandler();
|
||||
MethodAccess handler = this.handlerMetadata.getHandler();
|
||||
int methodIndex = this.handlerMetadata.getMethodIndex();
|
||||
|
||||
for (Object listener : this.listeners) {
|
||||
try {
|
||||
this.invocation.invoke(listener, handler, messages);
|
||||
this.invocation.invoke(listener, handler, methodIndex, messages);
|
||||
} catch (IllegalAccessException e) {
|
||||
errorHandler.handlePublicationError(new PublicationError()
|
||||
.setMessage("Error during invocation of message handler. " +
|
||||
"The class or method is not accessible")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(messages));
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -330,7 +295,7 @@ public class Subscription {
|
|||
"Wrong arguments passed to method. Was: " + Arrays.deepToString(messages)
|
||||
+ "Expected: " + Arrays.deepToString(handler.getParameterTypes()))
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(messages));
|
||||
} catch (InvocationTargetException e) {
|
||||
|
@ -338,7 +303,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"Message handler threw exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(messages));
|
||||
} catch (Throwable e) {
|
||||
|
@ -346,7 +311,7 @@ public class Subscription {
|
|||
.setMessage("Error during invocation of message handler. " +
|
||||
"The handler code threw an exception")
|
||||
.setCause(e)
|
||||
.setHandler(handler)
|
||||
.setMethodName(handler.getMethodNames()[methodIndex])
|
||||
.setListener(listener)
|
||||
.setPublishedObject(messages));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user