浏览代码

jfinal 4.8

James 6 年之前
父节点
当前提交
a7b7acfe40

+ 1 - 1
src/main/java/com/jfinal/template/expr/ast/Method.java

@@ -79,7 +79,7 @@ public class Method extends Expr {
 		try {
 			
 			MethodInfo methodInfo = MethodKit.getMethod(target.getClass(), methodName, argValues);
-			if (methodInfo != null) {
+			if (methodInfo.notNull()) {
 				return methodInfo.invoke(target, argValues);
 			}
 			

+ 23 - 0
src/main/java/com/jfinal/template/expr/ast/MethodInfo.java

@@ -93,6 +93,29 @@ public class MethodInfo {
 		}
 		return ret.append(")").toString();
 	}
+	
+	// --------- 以下代码仅用于支持 NullMethodInfo
+	
+	/**
+	 * 仅供 NullMethodInfo 继承使用
+	 */
+	protected MethodInfo() {
+		this.key = null;
+		this.clazz = null;
+		this.method = null;
+		this.isVarArgs = false;
+		this.paraTypes = null;
+	}
+	
+	/**
+	 * 仅仅 NullMethodInfo 会覆盖此方法并返回 false
+	 *
+	 * 1:MethodKit.getMethod(...) 消除 instanceof 判断
+	 * 2:Method.exec(...) 消除 null 值判断
+	 */
+	public boolean notNull() {
+		return true;
+	}
 }
 
 

+ 11 - 27
src/main/java/com/jfinal/template/expr/ast/MethodKit.java

@@ -41,7 +41,7 @@ public class MethodKit {
 	private static final Set<String> forbiddenMethods = new HashSet<String>(64);
 	private static final Set<Class<?>> forbiddenClasses = new HashSet<Class<?>>(64);
 	private static final Map<Class<?>, Class<?>> primitiveMap = new HashMap<Class<?>, Class<?>>(64);
-	private static final SyncWriteMap<Long, Object> methodCache = new SyncWriteMap<Long, Object>(2048, 0.25F);
+	private static final SyncWriteMap<Long, MethodInfo> methodCache = new SyncWriteMap<Long, MethodInfo>(2048, 0.25F);
 	
 	// 初始化在模板中调用 method 时所在的被禁止使用类
 	static {
@@ -124,36 +124,17 @@ public class MethodKit {
 	public static MethodInfo getMethod(Class<?> targetClass, String methodName, Object[] argValues) {
 		Class<?>[] argTypes = getArgTypes(argValues);
 		Long key = getMethodKey(targetClass, methodName, argTypes);
-		Object method = methodCache.get(key);
+		MethodInfo method = methodCache.get(key);
 		if (method == null) {
+			// 已确保不会返回 null,对于不存在的 Method,只进行一次获取操作
+			// 提升 null safe 表达式性能,未来需要考虑内存泄漏风险
 			method = doGetMethod(key, targetClass, methodName, argTypes);
-			if (method != null) {
-				methodCache.putIfAbsent(key, method);
-			} else {
-				// 对于不存在的 Method,只进行一次获取操作,主要为了支持 null safe,未来需要考虑内存泄漏风险
-				methodCache.putIfAbsent(key, Void.class);
-			}
+			methodCache.putIfAbsent(key, method);
 		}
-		return method instanceof MethodInfo ? (MethodInfo)method : null;
+		
+		return method;
 	}
 	
-	/**
-	 * 获取 getter 方法
-	 * 使用与 Field 相同的 key,避免生成两次 key值
-	 * ---> jfinal 3.5 已将此功能转移至 FieldKit
-	public static MethodInfo getGetterMethod(Long key, Class<?> targetClass, String methodName) {
-		Object getterMethod = methodCache.get(key);
-		if (getterMethod == null) {
-			getterMethod = doGetMethod(key, targetClass, methodName, NULL_ARG_TYPES);
-			if (getterMethod != null) {
-				methodCache.putIfAbsent(key, getterMethod);
-			} else {
-				methodCache.putIfAbsent(key, Void.class);
-			}
-		}
-		return getterMethod instanceof MethodInfo ? (MethodInfo)getterMethod : null;
-	} */
-	
 	static Class<?>[] getArgTypes(Object[] argValues) {
 		if (argValues == null || argValues.length == 0) {
 			return NULL_ARG_TYPES;
@@ -169,7 +150,9 @@ public class MethodKit {
 		if (forbiddenClasses.contains(targetClass)) {
 			throw new RuntimeException("Forbidden class: " + targetClass.getName());
 		}
+		
 		// 仅开启 forbiddenClasses 检测
+		// Method、SharedMethod、StaticMethod 已用 MethodKit.isForbiddenMethod(...) 检测
 		// if (forbiddenMethods.contains(methodName)) {
 		// 	throw new RuntimeException("Forbidden method: " + methodName);
 		// }
@@ -186,7 +169,8 @@ public class MethodKit {
 				}
 			}
 		}
-		return null;
+		
+		return NullMethodInfo.me;
 	}
 	
 	static boolean matchFixedArgTypes(Class<?>[] paraTypes, Class<?>[] argTypes) {

+ 9 - 1
src/main/java/com/jfinal/template/expr/ast/StaticMethod.java

@@ -50,6 +50,14 @@ public class StaticMethod extends Expr {
 		} catch (Exception e) {
 			throw new ParseException(e.getMessage(), location, e);
 		}
+		
+		if (MethodKit.isForbiddenClass(this.clazz)) {
+			throw new ParseException("Forbidden class: " + this.clazz.getName(), location);
+		}
+		if (MethodKit.isForbiddenMethod(methodName)) {
+			throw new ParseException("Forbidden method: " + methodName, location);
+		}
+		
 		this.methodName = methodName;
 		this.exprList = exprList;
 		this.location = location;
@@ -61,7 +69,7 @@ public class StaticMethod extends Expr {
 		try {
 			MethodInfo methodInfo = MethodKit.getMethod(clazz, methodName, argValues);
 			
-			if (methodInfo != null) {
+			if (methodInfo.notNull()) {
 				if (methodInfo.isStatic()) {
 					return methodInfo.invoke(null, argValues);
 				} else {