Skip to content

Commit

Permalink
Introduced DefaultParameterNameDiscoverer which checks JDK 8's standa…
Browse files Browse the repository at this point in the history
…rd reflection first and then falls back to ASM-based debug symbol analysis

Also, StandardReflectionParameterNameDiscoverer calls "Parameter.isNamePresent()" now to return null (and pass on to the next discoverer) if no JDK 8 parameters are available. Note that this requires OpenJDK 8 b100 or higher to compile now.

Issue: SPR-10532
  • Loading branch information
jhoeller authored and unknown committed Aug 8, 2013
1 parent f9325a8 commit 1420b97
Show file tree
Hide file tree
Showing 13 changed files with 97 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -37,9 +37,8 @@
import org.springframework.aop.support.ComposablePointcut;
import org.springframework.aop.support.MethodMatchers;
import org.springframework.aop.support.StaticMethodMatcher;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.PrioritizedParameterNameDiscoverer;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
Expand Down Expand Up @@ -435,15 +434,13 @@ private void bindArgumentsByName(int numArgumentsExpectingToBind) {

/**
* Create a ParameterNameDiscoverer to be used for argument binding.
* <p>The default implementation creates a {@link PrioritizedParameterNameDiscoverer}
* containing a {@link LocalVariableTableParameterNameDiscoverer} and an
* {@link AspectJAdviceParameterNameDiscoverer}.
* <p>The default implementation creates a {@link DefaultParameterNameDiscoverer}
* and adds a specifically configured {@link AspectJAdviceParameterNameDiscoverer}.
*/
protected ParameterNameDiscoverer createParameterNameDiscoverer() {
// We need to discover them, or if that fails, guess,
// and if we can't guess with 100% accuracy, fail.
PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
discoverer.addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
new AspectJAdviceParameterNameDiscoverer(this.pointcut.getExpression());
adviceParameterNameDiscoverer.setReturningName(this.returningName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
import org.aspectj.runtime.internal.AroundClosure;

import org.springframework.aop.ProxyMethodInvocation;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.util.Assert;

/**
Expand All @@ -51,6 +52,8 @@
*/
public class MethodInvocationProceedingJoinPoint implements ProceedingJoinPoint, JoinPoint.StaticPart {

private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

private final ProxyMethodInvocation methodInvocation;

private Object[] defensiveCopyOfArgs;
Expand Down Expand Up @@ -213,7 +216,7 @@ public Class[] getParameterTypes() {
@Override
public String[] getParameterNames() {
if (this.parameterNames == null) {
this.parameterNames = (new LocalVariableTableParameterNameDiscoverer()).getParameterNames(getMethod());
this.parameterNames = parameterNameDiscoverer.getParameterNames(getMethod());
}
return this.parameterNames;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -59,9 +59,6 @@
*/
public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {

protected static final ParameterNameDiscoverer ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER =
new AspectJAnnotationParameterNameDiscoverer();

private static final String AJC_MAGIC = "ajc$";


Expand Down Expand Up @@ -96,14 +93,8 @@ private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());

protected final ParameterNameDiscoverer parameterNameDiscoverer;

protected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();

protected AbstractAspectJAdvisorFactory() {
PrioritizedParameterNameDiscoverer prioritizedParameterNameDiscoverer = new PrioritizedParameterNameDiscoverer();
prioritizedParameterNameDiscoverer.addDiscoverer(ASPECTJ_ANNOTATION_PARAMETER_NAME_DISCOVERER);
this.parameterNameDiscoverer = prioritizedParameterNameDiscoverer;
}

/**
* We consider something to be an AspectJ aspect suitable for use by the Spring AOP system
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.PriorityOrdered;
Expand Down Expand Up @@ -120,7 +120,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

/** Resolver strategy for method parameter names */
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

/** Whether to automatically try to resolve circular references between beans */
private boolean allowCircularReferences = true;
Expand Down Expand Up @@ -191,7 +191,7 @@ protected InstantiationStrategy getInstantiationStrategy() {
/**
* Set the ParameterNameDiscoverer to use for resolving method parameter
* names if needed (e.g. for constructor names).
* <p>The default is {@link LocalVariableTableParameterNameDiscoverer}.
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.cache.Cache;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
Expand All @@ -46,7 +46,7 @@ class ExpressionEvaluator {
private final SpelExpressionParser parser = new SpelExpressionParser();

// shared param discoverer since it caches data internally
private final ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private final ParameterNameDiscoverer paramNameDiscoverer = new DefaultParameterNameDiscoverer();

private final Map<String, Expression> keyCache = new ConcurrentHashMap<String, Expression>(64);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.jmx.support.JmxUtils;

Expand Down Expand Up @@ -180,7 +180,7 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean

private boolean exposeClassDescriptor = false;

private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();


/**
Expand Down Expand Up @@ -262,7 +262,7 @@ protected boolean isExposeClassDescriptor() {
/**
* Set the ParameterNameDiscoverer to use for resolving method parameter
* names if needed (e.g. for parameter names of MBean operation methods).
* <p>The default is {@link LocalVariableTableParameterNameDiscoverer}.
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.io.Resource;
import org.springframework.util.ClassUtils;
Expand Down Expand Up @@ -93,7 +93,7 @@ public class LocalValidatorFactoryBean extends SpringValidatorAdapter

private ConstraintValidatorFactory constraintValidatorFactory;

private ParameterNameDiscoverer parameterNameDiscoverer;
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

private Resource[] mappingLocations;

Expand Down Expand Up @@ -161,7 +161,7 @@ public void setConstraintValidatorFactory(ConstraintValidatorFactory constraintV
/**
* Set the ParameterNameDiscoverer to use for resolving method and constructor
* parameter names if needed for message interpolation.
* <p>Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}.
* <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
Expand Down Expand Up @@ -269,8 +269,7 @@ private void configureParameterNameProviderIfPossible(Configuration configuratio
Configuration.class.getMethod("parameterNameProvider", parameterNameProviderClass);
final Object defaultProvider = ReflectionUtils.invokeMethod(
Configuration.class.getMethod("getDefaultParameterNameProvider"), configuration);
final ParameterNameDiscoverer discoverer = (this.parameterNameDiscoverer != null ?
this.parameterNameDiscoverer : new LocalVariableTableParameterNameDiscoverer());
final ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
Object parameterNameProvider = Proxy.newProxyInstance(getClass().getClassLoader(),
new Class[] {parameterNameProviderClass}, new InvocationHandler() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.core;

/**
* Default implementation of the {@link ParameterNameDiscoverer} strategy interface,
* using the Java 8 standard reflection mechanism (if available), and falling back
* to the ASM-based {@link LocalVariableTableParameterNameDiscoverer} for checking
* debug information in the class file.
*
* <p>Further discoverers may be added through {@link #addDiscoverer(ParameterNameDiscoverer)}.
*
* @author Juergen Hoeller
* @since 4.0
* @see StandardReflectionParameterNameDiscoverer
* @see LocalVariableTableParameterNameDiscoverer
*/
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer {

private static final boolean standardReflectionAvailable =
(JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_18);


public DefaultParameterNameDiscoverer() {
if (standardReflectionAvailable) {
addDiscoverer(new StandardReflectionParameterNameDiscoverer());
}
addDiscoverer(new LocalVariableTableParameterNameDiscoverer());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

import org.springframework.util.ClassUtils;

/**
* {@link ParameterNameDiscoverer} implementation which uses JDK 8's
* reflection facilities for introspecting parameter names.
Expand All @@ -35,7 +37,11 @@ public String[] getParameterNames(Method method) {
Parameter[] parameters = method.getParameters();
String[] parameterNames = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parameterNames[i] = parameters[i].getName();
Parameter param = parameters[i];
if (!param.isNamePresent()) {
return null;
}
parameterNames[i] = param.getName();
}
return parameterNames;
}
Expand All @@ -45,7 +51,11 @@ public String[] getParameterNames(Constructor<?> ctor) {
Parameter[] parameters = ctor.getParameters();
String[] parameterNames = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parameterNames[i] = parameters[i].getName();
Parameter param = parameters[i];
if (!param.isNamePresent()) {
return null;
}
parameterNames[i] = param.getName();
}
return parameterNames;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
import java.lang.reflect.Method;
import java.util.Arrays;

import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.util.ReflectionUtils;
Expand Down Expand Up @@ -51,7 +51,7 @@ public class InvocableHandlerMethod extends HandlerMethod {

private WebDataBinderFactory dataBinderFactory;

private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();


/**
Expand Down Expand Up @@ -97,8 +97,9 @@ public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverCompo
}

/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed (e.g. default request attribute name).
* <p>Default is an {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer} instance.
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.Ordered;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.AnnotationUtils;
Expand Down Expand Up @@ -138,7 +138,7 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator

private boolean synchronizeOnSession = false;

private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

private WebArgumentResolver[] customArgumentResolvers;

Expand Down Expand Up @@ -211,7 +211,7 @@ public void setSynchronizeOnSession(boolean synchronizeOnSession) {
/**
* Set the ParameterNameDiscoverer to use for resolving method parameter
* names if needed (e.g. for default attribute names).
* <p>Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}.
* <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.Ordered;
import org.springframework.core.ParameterNameDiscoverer;
Expand Down Expand Up @@ -173,7 +174,7 @@ public class AnnotationMethodHandlerAdapter extends WebContentGenerator

private boolean synchronizeOnSession = false;

private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();

private WebArgumentResolver[] customArgumentResolvers;

Expand Down Expand Up @@ -312,7 +313,7 @@ public void setSynchronizeOnSession(boolean synchronizeOnSession) {
/**
* Set the ParameterNameDiscoverer to use for resolving method parameter names if needed
* (e.g. for default attribute names).
* <p>Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}.
* <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
Expand Down
Loading

0 comments on commit 1420b97

Please sign in to comment.