From 0fb4af6b599c9bda39211d0732a71b81cf179da0 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 28 Dec 2009 18:57:15 +0000 Subject: [PATCH] generic ApplicationListener event type gets detected through proxy as well --- .../event/GenericApplicationListenerAdapter.java | 7 +++++++ .../event/ApplicationContextEventTests.java | 16 ++++++++++++++++ .../core/GenericTypeResolver.java | 6 +++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/org.springframework.context/src/main/java/org/springframework/context/event/GenericApplicationListenerAdapter.java b/org.springframework.context/src/main/java/org/springframework/context/event/GenericApplicationListenerAdapter.java index 2b5d8b99e9..087dcf46fa 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/event/GenericApplicationListenerAdapter.java +++ b/org.springframework.context/src/main/java/org/springframework/context/event/GenericApplicationListenerAdapter.java @@ -16,6 +16,7 @@ package org.springframework.context.event; +import org.springframework.aop.support.AopUtils; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.core.GenericTypeResolver; @@ -52,6 +53,12 @@ public class GenericApplicationListenerAdapter implements SmartApplicationListen public boolean supportsEventType(Class eventType) { Class typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class); + if (typeArg == null || typeArg.equals(ApplicationEvent.class)) { + Class targetClass = AopUtils.getTargetClass(this.delegate); + if (targetClass != this.delegate.getClass()) { + typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class); + } + } return (typeArg == null || typeArg.isAssignableFrom(eventType)); } diff --git a/org.springframework.context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java b/org.springframework.context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java index d94c65cd3b..06c598c9e7 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java +++ b/org.springframework.context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java @@ -25,6 +25,7 @@ import static org.easymock.EasyMock.*; import static org.junit.Assert.*; import org.junit.Test; +import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.TestBean; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -71,6 +72,21 @@ public class ApplicationContextEventTests { smc.multicastEvent(new MyOtherEvent(this)); } + @Test + public void proxiedListeners() { + MyOrderedListener1 listener1 = new MyOrderedListener1(); + MyOrderedListener2 listener2 = new MyOrderedListener2(listener1); + ApplicationListener proxy1 = (ApplicationListener) new ProxyFactory(listener1).getProxy(); + ApplicationListener proxy2 = (ApplicationListener) new ProxyFactory(listener2).getProxy(); + + SimpleApplicationEventMulticaster smc = new SimpleApplicationEventMulticaster(); + smc.addApplicationListener(proxy1); + smc.addApplicationListener(proxy2); + + smc.multicastEvent(new MyEvent(this)); + smc.multicastEvent(new MyOtherEvent(this)); + } + @Test public void testEventPublicationInterceptor() throws Throwable { MethodInvocation invocation = EasyMock.createMock(MethodInvocation.class); diff --git a/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java b/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java index 7017cbea97..0e44d19578 100644 --- a/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java +++ b/org.springframework.core/src/main/java/org/springframework/core/GenericTypeResolver.java @@ -147,7 +147,11 @@ public abstract class GenericTypeResolver { for (int i = 0; i < typeArgs.length; i++) { Type arg = typeArgs[i]; if (arg instanceof TypeVariable) { - arg = getTypeVariableMap(ownerClass).get((TypeVariable) arg); + TypeVariable tv = (TypeVariable) arg; + arg = getTypeVariableMap(ownerClass).get(tv); + if (arg == null) { + arg = extractBoundForTypeVariable(tv); + } } result[i] = (arg instanceof Class ? (Class) arg : Object.class); }