最近在用CXF restful ,cxf3 集成了Validation, 但hibernate validation返回的异常信息里不能准确的显示出方法参数签名,只能以arg0 arg1来表示参数,对于我们的外部api来说我只能说hibernate做的真烂,spring 在处理这方面就做的很好,最后还是借用下spring的类来实现,下面给出spring的如何获取参数方法签名。
@Test
public void testParameterName() {
DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
AccountService service = new AccountService();
Method[] methods = service.getClass().getDeclaredMethods();
for (Method method : methods) {
String[] result = discoverer.getParameterNames(method);
if (result != null) {
for (String name : result) {
System.out.println(name);
}
}
}
}
public class AccountService {
public String getAccountName(String id, int sex){
return "test";
}
}
@Override
public String[] getParameterNames(Method method) {
for (ParameterNameDiscoverer pnd : this.parameterNameDiscoverers) {
String[] result = pnd.getParameterNames(method);//看下面实现
if (result != null) {
return result;
}
}
return null;
}
org.springframework.core.LocalVariableTableParameterNameDiscoverer.getParameterNames(Method)
@Override
public String[] getParameterNames(Method method) {
Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
Class<?> declaringClass = originalMethod.getDeclaringClass();
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);//参数缓存
if (map == null) {
map = inspectClass(declaringClass);//
this.parameterNamesCache.put(declaringClass, map);
}
if (map != NO_DEBUG_INFO_MAP) {
return map.get(originalMethod);
}
return null;
}
/**
<span style="white-space:pre"> </span>* Inspects the target class. Exceptions will be logged and a maker map returned
<span style="white-space:pre"> </span> * to indicate the lack of debug information.
<span style="white-space:pre"> </span>*/
<span style="white-space:pre"> </span>private Map<Member, String[]> inspectClass(Class<?> clazz) {
<span style="white-space:pre"> </span>InputStream is = clazz.getResourceAsStream(ClassUtils.getClassFileName(clazz));
<span style="white-space:pre"> </span>if (is == null) {//看类是否可以加载
<span style="white-space:pre"> </span>// We couldn't load the class file, which is not fatal as it
<span style="white-space:pre"> </span>// simply means this method of discovering parameter names won't work.
<span style="white-space:pre"> </span>if (logger.isDebugEnabled()) {
<span style="white-space:pre"> </span>logger.debug("Cannot find '.class' file for class [" + clazz +
<span style="white-space:pre"> </span>"] - unable to determine constructor/method parameter names");
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return NO_DEBUG_INFO_MAP;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>ClassReader classReader = new ClassReader(is);//spring核心包ASM类解析工具
<span style="white-space:pre"> </span>Map<Member, String[]> map = new ConcurrentHashMap<Member, String[]>(32);
<span style="white-space:pre"> </span>classReader.accept(new ParameterNameDiscoveringVisitor(clazz, map), 0);
<span style="white-space:pre"> </span>return map;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>catch (IOException ex) {
<span style="white-space:pre"> </span>if (logger.isDebugEnabled()) {
<span style="white-space:pre"> </span>logger.debug("Exception thrown while reading '.class' file for class [" + clazz +
<span style="white-space:pre"> </span>"] - unable to determine constructor/method parameter names", ex);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>catch (IllegalArgumentException ex) {
<span style="white-space:pre"> </span>if (logger.isDebugEnabled()) {
<span style="white-space:pre"> </span>logger.debug("ASM ClassReader failed to parse class file [" + clazz +
<span style="white-space:pre"> </span>"], probably due to a new Java class file version that isn't supported yet " +
<span style="white-space:pre"> </span>"- unable to determine constructor/method parameter names", ex);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>finally {
<span style="white-space:pre"> </span>try {
<span style="white-space:pre"> </span>is.close();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>catch (IOException ex) {
<span style="white-space:pre"> </span>// ignore
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return NO_DEBUG_INFO_MAP;
<span style="white-space:pre"> </span>}