Browse Source

Consistent bean type checking for endpoint handlers

Issue: SPR-13725
pull/929/head
Juergen Hoeller 9 years ago
parent
commit
a0747c2148
  1. 4
      spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java
  2. 30
      spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java
  3. 31
      spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java
  4. 18
      spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java

4
spring-context/src/main/java/org/springframework/context/event/EventListenerMethodProcessor.java

@ -72,8 +72,8 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton, @@ -72,8 +72,8 @@ public class EventListenerMethodProcessor implements SmartInitializingSingleton,
@Override
public void afterSingletonsInstantiated() {
List<EventListenerFactory> factories = getEventListenerFactories();
String[] allBeanNames = this.applicationContext.getBeanNamesForType(Object.class);
for (String beanName : allBeanNames) {
String[] beanNames = this.applicationContext.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class<?> type = null;
try {

30
spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java

@ -456,8 +456,8 @@ public abstract class AnnotationUtils { @@ -456,8 +456,8 @@ public abstract class AnnotationUtils {
private static <A extends Annotation> Set<A> getRepeatableAnnotations(AnnotatedElement annotatedElement,
Class<A> annotationType, Class<? extends Annotation> containerAnnotationType, boolean declaredMode) {
Assert.notNull(annotatedElement, "annotatedElement must not be null");
Assert.notNull(annotationType, "annotationType must not be null");
Assert.notNull(annotatedElement, "AnnotatedElement must not be null");
Assert.notNull(annotationType, "Annotation type must not be null");
try {
if (annotatedElement instanceof Method) {
@ -488,6 +488,11 @@ public abstract class AnnotationUtils { @@ -488,6 +488,11 @@ public abstract class AnnotationUtils {
* @since 4.2
*/
public static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
Assert.notNull(annotatedElement, "AnnotatedElement must not be null");
if (annotationType == null) {
return null;
}
// Do NOT store result in the findAnnotationCache since doing so could break
// findAnnotation(Class, Class) and findAnnotation(Method, Class).
return synthesizeAnnotation(
@ -506,7 +511,6 @@ public abstract class AnnotationUtils { @@ -506,7 +511,6 @@ public abstract class AnnotationUtils {
*/
@SuppressWarnings("unchecked")
private static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType, Set<Annotation> visited) {
Assert.notNull(annotatedElement, "AnnotatedElement must not be null");
try {
Annotation[] anns = annotatedElement.getDeclaredAnnotations();
for (Annotation ann : anns) {
@ -546,6 +550,11 @@ public abstract class AnnotationUtils { @@ -546,6 +550,11 @@ public abstract class AnnotationUtils {
*/
@SuppressWarnings("unchecked")
public static <A extends Annotation> A findAnnotation(Method method, Class<A> annotationType) {
Assert.notNull(method, "Method must not be null");
if (annotationType == null) {
return null;
}
AnnotationCacheKey cacheKey = new AnnotationCacheKey(method, annotationType);
A result = (A) findAnnotationCache.get(cacheKey);
@ -663,6 +672,11 @@ public abstract class AnnotationUtils { @@ -663,6 +672,11 @@ public abstract class AnnotationUtils {
*/
@SuppressWarnings("unchecked")
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, boolean synthesize) {
Assert.notNull(clazz, "Class must not be null");
if (annotationType == null) {
return null;
}
AnnotationCacheKey cacheKey = new AnnotationCacheKey(clazz, annotationType);
A result = (A) findAnnotationCache.get(cacheKey);
if (result == null) {
@ -686,8 +700,6 @@ public abstract class AnnotationUtils { @@ -686,8 +700,6 @@ public abstract class AnnotationUtils {
*/
@SuppressWarnings("unchecked")
private static <A extends Annotation> A findAnnotation(Class<?> clazz, Class<A> annotationType, Set<Annotation> visited) {
Assert.notNull(clazz, "Class must not be null");
try {
Annotation[] anns = clazz.getDeclaredAnnotations();
for (Annotation ann : anns) {
@ -863,6 +875,11 @@ public abstract class AnnotationUtils { @@ -863,6 +875,11 @@ public abstract class AnnotationUtils {
public static boolean isAnnotationMetaPresent(Class<? extends Annotation> annotationType,
Class<? extends Annotation> metaAnnotationType) {
Assert.notNull(annotationType, "Annotation type must not be null");
if (metaAnnotationType == null) {
return false;
}
AnnotationCacheKey cacheKey = new AnnotationCacheKey(annotationType, metaAnnotationType);
Boolean metaPresent = metaPresentCache.get(cacheKey);
if (metaPresent != null) {
@ -1760,8 +1777,7 @@ public abstract class AnnotationUtils { @@ -1760,8 +1777,7 @@ public abstract class AnnotationUtils {
return false;
}
AnnotationCacheKey otherKey = (AnnotationCacheKey) other;
return (this.element.equals(otherKey.element) &&
ObjectUtils.nullSafeEquals(this.annotationType, otherKey.annotationType));
return (this.element.equals(otherKey.element) && this.annotationType.equals(otherKey.annotationType));
}
@Override

31
spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractMethodMessageHandler.java

@ -33,8 +33,8 @@ import org.apache.commons.logging.LogFactory; @@ -33,8 +33,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.MethodParameter;
import org.springframework.core.MethodIntrospector;
import org.springframework.core.MethodParameter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
@ -68,6 +68,19 @@ import org.springframework.util.concurrent.ListenableFutureCallback; @@ -68,6 +68,19 @@ import org.springframework.util.concurrent.ListenableFutureCallback;
public abstract class AbstractMethodMessageHandler<T>
implements MessageHandler, ApplicationContextAware, InitializingBean {
/**
* Bean name prefix for target beans behind scoped proxies. Used to exclude those
* targets from handler method detection, in favor of the corresponding proxies.
* <p>We're not checking the autowire-candidate status here, which is how the
* proxy target filtering problem is being handled at the autowiring level,
* since autowire-candidate may have been turned to {@code false} for other
* reasons, while still expecting the bean to be eligible for handler methods.
* <p>Originally defined in {@link org.springframework.aop.scope.ScopedProxyUtils}
* but duplicated here to avoid a hard dependency on the spring-aop module.
*/
private static final String SCOPED_TARGET_NAME_PREFIX = "scopedTarget.";
protected final Log logger = LogFactory.getLog(getClass());
private Collection<String> destinationPrefixes = new ArrayList<String>();
@ -218,8 +231,20 @@ public abstract class AbstractMethodMessageHandler<T> @@ -218,8 +231,20 @@ public abstract class AbstractMethodMessageHandler<T>
}
for (String beanName : this.applicationContext.getBeanNamesForType(Object.class)) {
if (isHandler(this.applicationContext.getType(beanName))){
detectHandlerMethods(beanName);
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;
try {
beanType = getApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
}

18
spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java

@ -175,9 +175,21 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap @@ -175,9 +175,21 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));
for (String name : beanNames) {
if (!name.startsWith(SCOPED_TARGET_NAME_PREFIX) && isHandler(getApplicationContext().getType(name))) {
detectHandlerMethods(name);
for (String beanName : beanNames) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;
try {
beanType = getApplicationContext().getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (beanType != null && isHandler(beanType)) {
detectHandlerMethods(beanName);
}
}
}
handlerMethodsInitialized(getHandlerMethods());

Loading…
Cancel
Save