ApplicationListenerMethodAdapter resolves order on construction

Issue: SPR-14642
This commit is contained in:
Juergen Hoeller 2016-08-30 20:50:02 +02:00
parent 391752abc2
commit 58fa63fdd1
2 changed files with 48 additions and 64 deletions

View File

@ -16,7 +16,6 @@
package org.springframework.context.event; package org.springframework.context.event;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException; import java.lang.reflect.UndeclaredThrowableException;
@ -53,6 +52,7 @@ import org.springframework.util.StringUtils;
* evaluated prior to invoking the underlying method. * evaluated prior to invoking the underlying method.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen
* @since 4.2 * @since 4.2
*/ */
@ -70,27 +70,59 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
private final List<ResolvableType> declaredEventTypes; private final List<ResolvableType> declaredEventTypes;
private final String condition;
private final int order;
private final AnnotatedElementKey methodKey; private final AnnotatedElementKey methodKey;
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
private EventExpressionEvaluator evaluator; private EventExpressionEvaluator evaluator;
private String condition;
private EventListener eventListener;
public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) { public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
this.beanName = beanName; this.beanName = beanName;
this.method = method; this.method = method;
this.targetClass = targetClass; this.targetClass = targetClass;
this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
this.declaredEventTypes = resolveDeclaredEventTypes();
this.methodKey = new AnnotatedElementKey(this.method, this.targetClass); EventListener ann = AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
this.condition = (ann != null ? ann.condition() : null);
this.order = resolveOrder(method);
this.methodKey = new AnnotatedElementKey(method, targetClass);
} }
private List<ResolvableType> resolveDeclaredEventTypes(Method method, EventListener ann) {
int count = method.getParameterCount();
if (count > 1) {
throw new IllegalStateException(
"Maximum one parameter is allowed for event listener method: " + method);
}
if (ann != null && ann.classes().length > 0) {
List<ResolvableType> types = new ArrayList<>(ann.classes().length);
for (Class<?> eventType : ann.classes()) {
types.add(ResolvableType.forClass(eventType));
}
return types;
}
else {
if (count == 0) {
throw new IllegalStateException(
"Event parameter is mandatory for event listener method: " + method);
}
return Collections.singletonList(ResolvableType.forMethodParameter(method, 0));
}
}
private int resolveOrder(Method method) {
Order ann = AnnotatedElementUtils.findMergedAnnotation(method, Order.class);
return (ann != null ? ann.value() : 0);
}
/** /**
* Initialize this instance. * Initialize this instance.
*/ */
@ -128,8 +160,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
@Override @Override
public int getOrder() { public int getOrder() {
Order order = getMethodAnnotation(Order.class); return this.order;
return (order != null ? order.value() : 0);
} }
@ -164,8 +195,8 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
if (this.method.getParameterCount() == 0) { if (this.method.getParameterCount() == 0) {
return new Object[0]; return new Object[0];
} }
if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.getRawClass()) &&
&& event instanceof PayloadApplicationEvent) { event instanceof PayloadApplicationEvent) {
return new Object[] {((PayloadApplicationEvent) event).getPayload()}; return new Object[] {((PayloadApplicationEvent) event).getPayload()};
} }
else { else {
@ -212,10 +243,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
return true; return true;
} }
protected <A extends Annotation> A getMethodAnnotation(Class<A> annotationType) {
return AnnotatedElementUtils.findMergedAnnotation(this.method, annotationType);
}
/** /**
* Invoke the event listener method with the given argument values. * Invoke the event listener method with the given argument values.
*/ */
@ -253,13 +280,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
return this.applicationContext.getBean(this.beanName); return this.applicationContext.getBean(this.beanName);
} }
protected EventListener getEventListener() {
if (this.eventListener == null) {
this.eventListener = AnnotatedElementUtils.findMergedAnnotation(this.method, EventListener.class);
}
return this.eventListener;
}
/** /**
* Return the condition to use. * Return the condition to use.
* <p>Matches the {@code condition} attribute of the {@link EventListener} * <p>Matches the {@code condition} attribute of the {@link EventListener}
@ -267,12 +287,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
* is meta-annotated with {@code @EventListener}. * is meta-annotated with {@code @EventListener}.
*/ */
protected String getCondition() { protected String getCondition() {
if (this.condition == null) {
EventListener eventListener = AnnotatedElementUtils.findMergedAnnotation(this.method, EventListener.class);
if (eventListener != null) {
this.condition = eventListener.condition();
}
}
return this.condition; return this.condition;
} }
@ -346,29 +360,6 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
return null; return null;
} }
private List<ResolvableType> resolveDeclaredEventTypes() {
int count = this.method.getParameterCount();
if (count > 1) {
throw new IllegalStateException(
"Maximum one parameter is allowed for event listener method: " + this.method);
}
EventListener ann = getEventListener();
if (ann != null && ann.classes().length > 0) {
List<ResolvableType> types = new ArrayList<>();
for (Class<?> eventType : ann.classes()) {
types.add(ResolvableType.forClass(eventType));
}
return types;
}
else {
if (count == 0) {
throw new IllegalStateException(
"Event parameter is mandatory for event listener method: " + this.method);
}
return Collections.singletonList(ResolvableType.forMethodParameter(this.method, 0));
}
}
@Override @Override
public String toString() { public String toString() {

View File

@ -18,9 +18,6 @@ package org.springframework.transaction.event;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ApplicationListenerMethodAdapter; import org.springframework.context.event.ApplicationListenerMethodAdapter;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
@ -41,14 +38,13 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
* bean of type {@link TransactionalEventListenerFactory} is required. * bean of type {@link TransactionalEventListenerFactory} is required.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Juergen Hoeller
* @since 4.2 * @since 4.2
* @see ApplicationListenerMethodAdapter * @see ApplicationListenerMethodAdapter
* @see TransactionalEventListener * @see TransactionalEventListener
*/ */
class ApplicationListenerMethodTransactionalAdapter extends ApplicationListenerMethodAdapter { class ApplicationListenerMethodTransactionalAdapter extends ApplicationListenerMethodAdapter {
protected final Log logger = LogFactory.getLog(getClass());
private final TransactionalEventListener annotation; private final TransactionalEventListener annotation;
@ -56,7 +52,7 @@ class ApplicationListenerMethodTransactionalAdapter extends ApplicationListenerM
super(beanName, targetClass, method); super(beanName, targetClass, method);
this.annotation = AnnotatedElementUtils.findMergedAnnotation(method, TransactionalEventListener.class); this.annotation = AnnotatedElementUtils.findMergedAnnotation(method, TransactionalEventListener.class);
if (this.annotation == null) { if (this.annotation == null) {
throw new IllegalStateException("No TransactionalEventListener annotation found on '" + method + "'"); throw new IllegalStateException("No TransactionalEventListener annotation found on method: " + method);
} }
} }
@ -68,15 +64,13 @@ class ApplicationListenerMethodTransactionalAdapter extends ApplicationListenerM
TransactionSynchronizationManager.registerSynchronization(transactionSynchronization); TransactionSynchronizationManager.registerSynchronization(transactionSynchronization);
} }
else if (this.annotation.fallbackExecution()) { else if (this.annotation.fallbackExecution()) {
if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK) { if (this.annotation.phase() == TransactionPhase.AFTER_ROLLBACK && logger.isWarnEnabled()) {
logger.warn("Processing '" + event + "' as a fallback execution on AFTER_ROLLBACK phase."); logger.warn("Processing " + event + " as a fallback execution on AFTER_ROLLBACK phase");
} }
processEvent(event); processEvent(event);
} }
else { else if (logger.isDebugEnabled()) {
if (logger.isDebugEnabled()) { logger.debug("No transaction is running - skipping " + event);
logger.debug("No transaction is running, skipping '" + event + "' for '" + this + "'");
}
} }
} }
@ -85,7 +79,6 @@ class ApplicationListenerMethodTransactionalAdapter extends ApplicationListenerM
} }
private static class TransactionSynchronizationEventAdapter extends TransactionSynchronizationAdapter { private static class TransactionSynchronizationEventAdapter extends TransactionSynchronizationAdapter {
private final ApplicationListenerMethodAdapter listener; private final ApplicationListenerMethodAdapter listener;