You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by il...@apache.org on 2019/08/20 06:33:23 UTC

[dubbo] branch master updated: Fix [3796] fix method parameter bean generation (#4859)

This is an automated email from the ASF dual-hosted git repository.

iluo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new d7e2ef4  Fix [3796] fix method parameter bean generation  (#4859)
d7e2ef4 is described below

commit d7e2ef42b98a80993da7044082c966d4e45f3140
Author: luryson <lu...@qq.com>
AuthorDate: Tue Aug 20 14:33:16 2019 +0800

    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
---
 .../validation/support/jvalidation/JValidator.java | 58 ++++++++++++++++------
 1 file changed, 42 insertions(+), 16 deletions(-)

diff --git a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
index 86775de..5d598ea 100644
--- a/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
+++ b/dubbo-filter/dubbo-filter-validation/src/main/java/org/apache/dubbo/validation/support/jvalidation/JValidator.java
@@ -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);
-            }
-            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 ctClass.toClass(clazz.getClassLoader(), null);
+            } else {
+                return Class.forName(parameterClassName, true, clazz.getClassLoader());
             }
-            return parameterBean;
-        } catch (Throwable e) {
-            logger.warn(e.getMessage(), e);
-            return null;
         }
     }