Class PatternMatchingMethodInvoker<ARGUMENT_COMMON_ROOT_TYPE>
- Type Parameters:
ARGUMENT_COMMON_ROOT_TYPE- The method argument common root type (i.e. a common superclass or common interface) for the argument-type that we're performing pattern matching on.
If there isn't a common root type, then you can specifyObjectinsteadExample: Within a single class we have placed a set methods that can handle
OrderEvent's, such asOrderCreated, OrderShipped, OrderAccepted, etc.
In this caseOrderEventwill be ourARGUMENT_ROOT_TYPEas it forms the root of the type hierarchy.
PatternMatchingMethodInvoker is to support pattern matching a set of typed methods against a
concrete argument and have the method(s) that match the type resolved by the MethodPatternMatcher.resolveInvocationArgumentTypeFromObject(Object) will be invoked by the MethodPatternMatcher.invokeMethod(Method, Object, Object, Class) with the argument
Example: Say we have a single class we have placed a set methods that can handle OrderEvent's, such as OrderCreated, OrderShipped, OrderAccepted, etc.
In this case OrderEvent will be our ARGUMENT_ROOT_TYPE as it forms the root of the type hierarchy.
ARGUMENT_ROOT_TYPE we need to determine how to match the methods.This involves several parts: 1. Method Pattern using
MethodPatternMatcher.isInvokableMethod(Method)
Example of methods patterns that matches the intention of this class:
- Annotation based - where an annotation marks the methods that should be matched:
@EventHandler private void some_name_that_we_do_not_care_about(OrderCreated t, ...) { ... } @EventHandler private void some_name_that_we_do_not_care_about(OrderAccepted t, ...) { ... } - Name based - where a specific name, e.g. "
on" in the example below, the methods that should be matched:private void on(OrderCreated t) { ... } private void on(OrderAccepted t) { ... } - Or some other patterns that you're interested in supporting
MethodPatternMatcher.resolveInvocationArgumentTypeFromMethodDefinition(Method)
3. Discover all methods matching the argument instance supplied to the invoke(Object)/invoke(Object, NoMatchingMethodsHandler) methods
After we've filtered out and found the methods that match our pattern, next phase is to figure out what methods match a concrete argument instance.Example: Let's say the
argument object is an instance of OrderAccepted and we're matching against the following methods
@EventHandler
private void method1(OrderEvent t) { ... }
@EventHandler
private void method2(OrderShipped t) { ... }
@EventHandler
private void method3(OrderAccepted t) { ... }
In this case both method1 and method3 match on type of the argument instance (OrderAccepted), because OrderEvent (of method1) match by hierarchy,
and OrderAccepted (of method3) match directly by type.
InvocationStrategy to determine which method(s) to invoke based on the concrete argument instance supplied to the invoke(Object)/invoke(Object, NoMatchingMethodsHandler) methods
InvocationStrategy.InvokeMostSpecificTypeMatched- in which case onlymethod3will be called, sinceOrderAcceptedis a more specific type than the more generic typeOrderEventInvocationStrategy.InvokeAllMatches- in which case BOTHmethod1andmethod3will be called in sequence (notice: the order of the methods called is not deterministic)
MethodPatternMatcher
For some methods, it's not necessarily the first argument that decides what argument-type the method supports and the method may need to be called with multiple arguments and not just one.E.g. when handling enveloped types (such as Messages that encapsulate a payload) we may want to match methods against the message' payload type instead of the message type
What methods is a candidate for matching, what type a given method supports and how the method is invoked is determined by
MethodPatternMatcher.For more simple cases the
SingleArgumentAnnotatedMethodPatternMatcher provides a good default implementation.
Logging
Using a setup where the PatternMatchingMethodInvoker is invoking methods on an instance of dk.cloudcreate.handlers.OrderEventsHandler
var patternMatchingInvoker = new PatternMatchingMethodInvoker<>(new dk.cloudcreate.handlers.OrderEventsHandler(),
new SingleArgumentAnnotatedMethodPatternMatcher(EventHandler.class,
OrderEvent.class),
InvocationStrategy.InvokeMostSpecificTypeMatched,
Optional.empty());
and you want PatternMatchingMethodInvoker logging then you should set the logging level for dk.cloudcreate.handlers.OrderEventsHandler to TRACE-
Constructor Summary
ConstructorsConstructorDescriptionPatternMatchingMethodInvoker(Object invokeMethodsOn, MethodPatternMatcher<ARGUMENT_COMMON_ROOT_TYPE> methodPatternMatcher, InvocationStrategy invocationStrategy) Setup a pattern matching method invoker using the default no-opNoMatchingMethodsHandlerPatternMatchingMethodInvoker(Object invokeMethodsOn, MethodPatternMatcher<ARGUMENT_COMMON_ROOT_TYPE> methodPatternMatcher, InvocationStrategy invocationStrategy, Optional<NoMatchingMethodsHandler> defaultNoMatchingMethodsHandler) -
Method Summary
Modifier and TypeMethodDescriptionbooleanhasMatchingMethod(Class<?> argumentType) voidInvoke matching methods based on theargumenton theinvokeMethodsOnbased on theMethodPatternMatcherandInvocationStrategyusing the defaultdefaultNoMatchingMethodsHandlerdefined in thePatternMatchingMethodInvoker(Object, MethodPatternMatcher, InvocationStrategy, Optional)voidinvoke(Object argument, NoMatchingMethodsHandler noMatchingMethodsHandler) Invoke matching methods based on theargumenton theinvokeMethodsOnbased on theMethodPatternMatcherandInvocationStrategy
-
Constructor Details
-
Method Details
-
invoke
Invoke matching methods based on theargumenton theinvokeMethodsOnbased on theMethodPatternMatcherandInvocationStrategyusing the defaultdefaultNoMatchingMethodsHandlerdefined in thePatternMatchingMethodInvoker(Object, MethodPatternMatcher, InvocationStrategy, Optional)- Parameters:
argument- The argument that will be forwarded to theMethodPatternMatcherfor method invocation
-
hasMatchingMethod
-