Browse Source

新增 Javassist 代理,支持 Java 17

James 2 years ago
parent
commit
d77c747a42

+ 2 - 2
src/main/java/com/jfinal/ext/proxy/CglibProxyFactory.java

@@ -34,9 +34,9 @@ public class CglibProxyFactory extends ProxyFactory {
 	public <T> T get(Class<T> target) {
 		// 被 cglib 代理过的类名包含 "$$EnhancerBy"。仅需调用一次 getSuperclass() 即可
 		if (target.getName().indexOf("$$EnhancerBy") > -1) {
-			target =(Class<T>) target.getSuperclass();
+			target = (Class<T>) target.getSuperclass();
 		}
-		return (T)net.sf.cglib.proxy.Enhancer.create(target, new CglibCallback());
+		return (T) net.sf.cglib.proxy.Enhancer.create(target, new CglibCallback());
 	}
 }
 

+ 80 - 0
src/main/java/com/jfinal/ext/proxy/JavassistCallback.java

@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2011-2023, James Zhan 詹波 (jfinal@126.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jfinal.ext.proxy;
+
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+import com.jfinal.aop.Interceptor;
+import com.jfinal.aop.InterceptorManager;
+import com.jfinal.aop.Invocation;
+import com.jfinal.ext.proxy.InterceptorCache.MethodKey;
+import javassist.util.proxy.MethodHandler;
+
+/**
+ * JavassistCallback.
+ */
+class JavassistCallback implements MethodHandler {
+	
+	private static final Set<String> excludedMethodName = buildExcludedMethodName();
+	private static final InterceptorManager interMan = InterceptorManager.me();
+	
+	@Override
+    public Object invoke(Object target, Method method, Method methodProxy, Object[] args) throws Throwable {
+		if (excludedMethodName.contains(method.getName())) {
+		    return methodProxy.invoke(target, args);
+		}
+		
+		Class<?> targetClass = target.getClass().getSuperclass();
+		
+		MethodKey key = InterceptorCache.getMethodKey(targetClass, method);
+		Interceptor[] inters = InterceptorCache.get(key);
+		if (inters == null) {
+			inters = interMan.buildServiceMethodInterceptor(targetClass, method);
+			InterceptorCache.put(key, inters);
+		}
+		
+		if (inters.length == 0) {
+		    return methodProxy.invoke(target, args);
+		}
+		
+		Invocation invocation = new Invocation(target, method, inters,
+			x -> {
+				return methodProxy.invoke(target, x);
+			}
+		, args);
+		invocation.invoke();
+		return invocation.getReturnValue();
+	}
+	
+	private static final Set<String> buildExcludedMethodName() {
+		Set<String> excludedMethodName = new HashSet<String>(64, 0.25F);
+		Method[] methods = Object.class.getDeclaredMethods();
+		for (Method m : methods) {
+			excludedMethodName.add(m.getName());
+		}
+		// getClass() registerNatives() can not be enhanced
+		// excludedMethodName.remove("getClass");	
+		// excludedMethodName.remove("registerNatives");
+		return excludedMethodName;
+	}
+}
+
+
+
+
+

+ 84 - 0
src/main/java/com/jfinal/ext/proxy/JavassistProxyFactory.java

@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) 2011-2023, James Zhan 詹波 (jfinal@126.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jfinal.ext.proxy;
+
+import java.util.Map;
+import com.jfinal.kit.SyncWriteMap;
+import com.jfinal.proxy.ProxyFactory;
+import javassist.util.proxy.ProxyObject;
+
+/**
+ * JavassistProxyFactory 用于扩展 javassist 的代理模式,默认不使用
+ * 
+ * <pre>
+ * 配置方法:
+ * public void configConstant(Constants me) {
+ *     ProxyManager.me().setProxyFactory(new JavassistProxyFactory());
+ * }
+ * </pre>
+ */
+public class JavassistProxyFactory extends ProxyFactory {
+    
+    protected Map<Class<?>, Class<?>> cache = new SyncWriteMap<>(1024, 0.25F);
+    protected JavassistCallback callback = new JavassistCallback();
+	
+    @SuppressWarnings("unchecked")
+    public <T> T get(Class<T> target) {
+        try {
+            // 被 javassist 代理过的类名包含 "_$$_"。不存在代理过两层的情况,仅需调用一次 getSuperclass() 即可
+            if (target.getName().indexOf("_$$_") > -1) {
+                target = (Class<T>) target.getSuperclass();
+            }
+            
+            Object ret;
+            Class<T> clazz = (Class<T>) cache.get(target);
+            if (clazz != null) {
+                ret = (T) clazz.newInstance();
+            } else {
+                ret = doGet(target);
+            }
+            
+            ((ProxyObject) ret).setHandler(callback);
+            return (T) ret;
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected <T> T doGet(Class<T> target) throws ReflectiveOperationException {
+        synchronized (target) {
+            Class<T> clazz = (Class<T>) cache.get(target);
+            if (clazz != null) {
+                return (T) clazz.newInstance();
+            }
+            
+            javassist.util.proxy.ProxyFactory factory = new javassist.util.proxy.ProxyFactory();
+            factory.setSuperclass(target);
+            clazz = (Class<T>) factory.createClass();
+            T ret = clazz.newInstance();
+            cache.put(target, clazz);
+            return ret;
+        }
+	}
+}
+
+
+
+
+
+