Fix [3796] fix method parameter bean generation (#4859)

* 封装验证参数实体时,增加同步控制,防止容器启动后第一次调用时的并发问题

封装验证参数实体时,增加同步控制,防止容器启动后第一次调用时的并发问题

* move relevant code to a new method

* add try block to catch NotFoundException when try to generate method-parameter-class
This commit is contained in:
luryson 2019-08-20 14:33:16 +08:00 committed by Ian Luo
parent 06f719086e
commit d7e2ef42b9
1 changed files with 42 additions and 16 deletions

View File

@ -119,8 +119,41 @@ public class JValidator implements Validator {
try {
parameterClass = Class.forName(parameterClassName, true, clazz.getClassLoader());
} catch (ClassNotFoundException e) {
ClassPool pool = ClassGenerator.getClassPool(clazz.getClassLoader());
CtClass ctClass = pool.makeClass(parameterClassName);
parameterClass = generateMethodParameterClass(clazz, method, parameterClassName);
}
Object parameterBean = parameterClass.newInstance();
for (int i = 0; i < args.length; i++) {
Field field = parameterClass.getField(method.getName() + "Argument" + i);
field.set(parameterBean, args[i]);
}
return parameterBean;
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
return null;
}
}
/**
* try to generate methodParameterClass.
*
* @param clazz interface class
* @param method invoke method
* @param parameterClassName generated parameterClassName
* @return Class<?> generated methodParameterClass
* @throws Exception
*/
private static Class<?> generateMethodParameterClass(Class<?> clazz, Method method, String parameterClassName)
throws Exception {
ClassPool pool = ClassGenerator.getClassPool(clazz.getClassLoader());
synchronized (parameterClassName.intern()) {
CtClass ctClass = null;
try {
ctClass = pool.getCtClass(parameterClassName);
} catch (NotFoundException ignore) {
}
if (null == ctClass) {
ctClass = pool.makeClass(parameterClassName);
ClassFile classFile = ctClass.getClassFile();
classFile.setVersionToJava5();
ctClass.addConstructor(CtNewConstructor.defaultConstructor(pool.getCtClass(parameterClassName)));
@ -134,16 +167,16 @@ public class JValidator implements Validator {
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
javassist.bytecode.annotation.Annotation ja = new javassist.bytecode.annotation.Annotation(
classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName()));
classFile.getConstPool(), pool.getCtClass(annotation.annotationType().getName()));
Method[] members = annotation.annotationType().getMethods();
for (Method member : members) {
if (Modifier.isPublic(member.getModifiers())
&& member.getParameterTypes().length == 0
&& member.getDeclaringClass() == annotation.annotationType()) {
&& member.getParameterTypes().length == 0
&& member.getDeclaringClass() == annotation.annotationType()) {
Object value = member.invoke(annotation);
if (null != value) {
MemberValue memberValue = createMemberValue(
classFile.getConstPool(), pool.get(member.getReturnType().getName()), value);
classFile.getConstPool(), pool.get(member.getReturnType().getName()), value);
ja.addMemberValue(member.getName(), memberValue);
}
}
@ -156,17 +189,10 @@ public class JValidator implements Validator {
ctField.getFieldInfo().addAttribute(attribute);
ctClass.addField(ctField);
}
parameterClass = ctClass.toClass(clazz.getClassLoader(), null);
return ctClass.toClass(clazz.getClassLoader(), null);
} else {
return Class.forName(parameterClassName, true, clazz.getClassLoader());
}
Object parameterBean = parameterClass.newInstance();
for (int i = 0; i < args.length; i++) {
Field field = parameterClass.getField(method.getName() + "Argument" + i);
field.set(parameterBean, args[i]);
}
return parameterBean;
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
return null;
}
}