Simplify LocalVariableTableParameterNameDiscoverer implementation
This commit refactors the internals of LocalVariableTableParameterNameDiscoverer to use java.lang.reflect.Executable in order to simplify the implementation.
This commit is contained in:
parent
309b328719
commit
699d3f15e8
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2018 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -19,7 +19,7 @@ package org.springframework.core;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Executable;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -51,6 +51,7 @@ import org.springframework.util.ClassUtils;
|
||||||
* @author Costin Leau
|
* @author Costin Leau
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class LocalVariableTableParameterNameDiscoverer implements ParameterNameDiscoverer {
|
public class LocalVariableTableParameterNameDiscoverer implements ParameterNameDiscoverer {
|
||||||
|
@ -58,40 +59,38 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
private static final Log logger = LogFactory.getLog(LocalVariableTableParameterNameDiscoverer.class);
|
private static final Log logger = LogFactory.getLog(LocalVariableTableParameterNameDiscoverer.class);
|
||||||
|
|
||||||
// marker object for classes that do not have any debug info
|
// marker object for classes that do not have any debug info
|
||||||
private static final Map<Member, String[]> NO_DEBUG_INFO_MAP = Collections.emptyMap();
|
private static final Map<Executable, String[]> NO_DEBUG_INFO_MAP = Collections.emptyMap();
|
||||||
|
|
||||||
// the cache uses a nested index (value is a map) to keep the top level cache relatively small in size
|
// the cache uses a nested index (value is a map) to keep the top level cache relatively small in size
|
||||||
private final Map<Class<?>, Map<Member, String[]>> parameterNamesCache = new ConcurrentHashMap<>(32);
|
private final Map<Class<?>, Map<Executable, String[]>> parameterNamesCache = new ConcurrentHashMap<>(32);
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public String[] getParameterNames(Method method) {
|
public String[] getParameterNames(Method method) {
|
||||||
Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
|
Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||||
Class<?> declaringClass = originalMethod.getDeclaringClass();
|
return doGetParameterNames(originalMethod);
|
||||||
Map<Member, String[]> map = this.parameterNamesCache.computeIfAbsent(declaringClass, this::inspectClass);
|
|
||||||
if (map != NO_DEBUG_INFO_MAP) {
|
|
||||||
return map.get(originalMethod);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public String[] getParameterNames(Constructor<?> ctor) {
|
public String[] getParameterNames(Constructor<?> ctor) {
|
||||||
Class<?> declaringClass = ctor.getDeclaringClass();
|
return doGetParameterNames(ctor);
|
||||||
Map<Member, String[]> map = this.parameterNamesCache.computeIfAbsent(declaringClass, this::inspectClass);
|
}
|
||||||
if (map != NO_DEBUG_INFO_MAP) {
|
|
||||||
return map.get(ctor);
|
@Nullable
|
||||||
}
|
private String[] doGetParameterNames(Executable executable) {
|
||||||
return null;
|
Class<?> declaringClass = executable.getDeclaringClass();
|
||||||
|
Map<Executable, String[]> map = this.parameterNamesCache.computeIfAbsent(declaringClass, this::inspectClass);
|
||||||
|
return (map != NO_DEBUG_INFO_MAP ? map.get(executable) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspects the target class. Exceptions will be logged and a maker map returned
|
* Inspects the target class.
|
||||||
* to indicate the lack of debug information.
|
* <p>Exceptions will be logged, and a marker map returned to indicate the
|
||||||
|
* lack of debug information.
|
||||||
*/
|
*/
|
||||||
private Map<Member, String[]> inspectClass(Class<?> clazz) {
|
private Map<Executable, String[]> inspectClass(Class<?> clazz) {
|
||||||
InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));
|
InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));
|
||||||
if (is == null) {
|
if (is == null) {
|
||||||
// We couldn't load the class file, which is not fatal as it
|
// We couldn't load the class file, which is not fatal as it
|
||||||
|
@ -104,7 +103,7 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ClassReader classReader = new ClassReader(is);
|
ClassReader classReader = new ClassReader(is);
|
||||||
Map<Member, String[]> map = new ConcurrentHashMap<>(32);
|
Map<Executable, String[]> map = new ConcurrentHashMap<>(32);
|
||||||
classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0);
|
classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
@ -134,8 +133,8 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class that inspects all methods (constructor included) and then
|
* Helper class that inspects all methods and constructors and then
|
||||||
* attempts to find the parameter names for that member.
|
* attempts to find the parameter names for the given {@link Executable}.
|
||||||
*/
|
*/
|
||||||
private static class ParameterNameDiscoveringVisitor extends ClassVisitor {
|
private static class ParameterNameDiscoveringVisitor extends ClassVisitor {
|
||||||
|
|
||||||
|
@ -143,12 +142,12 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
|
|
||||||
private final Class<?> clazz;
|
private final Class<?> clazz;
|
||||||
|
|
||||||
private final Map<Member, String[]> memberMap;
|
private final Map<Executable, String[]> executableMap;
|
||||||
|
|
||||||
public ParameterNameDiscoveringVisitor(Class<?> clazz, Map<Member, String[]> memberMap) {
|
public ParameterNameDiscoveringVisitor(Class<?> clazz, Map<Executable, String[]> executableMap) {
|
||||||
super(SpringAsmInfo.ASM_VERSION);
|
super(SpringAsmInfo.ASM_VERSION);
|
||||||
this.clazz = clazz;
|
this.clazz = clazz;
|
||||||
this.memberMap = memberMap;
|
this.executableMap = executableMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -156,7 +155,7 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||||
// exclude synthetic + bridged && static class initialization
|
// exclude synthetic + bridged && static class initialization
|
||||||
if (!isSyntheticOrBridged(access) && !STATIC_CLASS_INIT.equals(name)) {
|
if (!isSyntheticOrBridged(access) && !STATIC_CLASS_INIT.equals(name)) {
|
||||||
return new LocalVariableTableVisitor(this.clazz, this.memberMap, name, desc, isStatic(access));
|
return new LocalVariableTableVisitor(this.clazz, this.executableMap, name, desc, isStatic(access));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +176,7 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
|
|
||||||
private final Class<?> clazz;
|
private final Class<?> clazz;
|
||||||
|
|
||||||
private final Map<Member, String[]> memberMap;
|
private final Map<Executable, String[]> executableMap;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
@ -195,10 +194,10 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
*/
|
*/
|
||||||
private final int[] lvtSlotIndex;
|
private final int[] lvtSlotIndex;
|
||||||
|
|
||||||
public LocalVariableTableVisitor(Class<?> clazz, Map<Member, String[]> map, String name, String desc, boolean isStatic) {
|
public LocalVariableTableVisitor(Class<?> clazz, Map<Executable, String[]> map, String name, String desc, boolean isStatic) {
|
||||||
super(SpringAsmInfo.ASM_VERSION);
|
super(SpringAsmInfo.ASM_VERSION);
|
||||||
this.clazz = clazz;
|
this.clazz = clazz;
|
||||||
this.memberMap = map;
|
this.executableMap = map;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.args = Type.getArgumentTypes(desc);
|
this.args = Type.getArgumentTypes(desc);
|
||||||
this.parameterNames = new String[this.args.length];
|
this.parameterNames = new String[this.args.length];
|
||||||
|
@ -223,11 +222,11 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
// which doesn't use any local variables.
|
// which doesn't use any local variables.
|
||||||
// This means that hasLvtInfo could be false for that kind of methods
|
// This means that hasLvtInfo could be false for that kind of methods
|
||||||
// even if the class has local variable info.
|
// even if the class has local variable info.
|
||||||
this.memberMap.put(resolveMember(), this.parameterNames);
|
this.executableMap.put(resolveExecutable(), this.parameterNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Member resolveMember() {
|
private Executable resolveExecutable() {
|
||||||
ClassLoader loader = this.clazz.getClassLoader();
|
ClassLoader loader = this.clazz.getClassLoader();
|
||||||
Class<?>[] argTypes = new Class<?>[this.args.length];
|
Class<?>[] argTypes = new Class<?>[this.args.length];
|
||||||
for (int i = 0; i < this.args.length; i++) {
|
for (int i = 0; i < this.args.length; i++) {
|
||||||
|
|
Loading…
Reference in New Issue