diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java index 7cbdb96d5..c93dd0163 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/BeanDescFactory.java @@ -15,8 +15,7 @@ package org.dromara.hutool.core.bean; import org.dromara.hutool.core.array.ArrayUtil; import org.dromara.hutool.core.map.reference.WeakConcurrentMap; import org.dromara.hutool.core.reflect.FieldUtil; - -import java.lang.reflect.Proxy; +import org.dromara.hutool.core.reflect.JdkProxyUtil; /** * Bean描述信息工厂类
@@ -52,7 +51,7 @@ public class BeanDescFactory { public static BeanDesc getBeanDescWithoutCache(final Class clazz) { if (RecordUtil.isRecord(clazz)) { return new RecordBeanDesc(clazz); - } else if (isProxyClass(clazz) || ArrayUtil.isEmpty(FieldUtil.getFields(clazz))) { + } else if (JdkProxyUtil.isProxyClass(clazz) || ArrayUtil.isEmpty(FieldUtil.getFields(clazz))) { // 代理类和空字段的Bean不支持属性获取,直接使用方法方式 return new SimpleBeanDesc(clazz); } else { @@ -68,11 +67,4 @@ public class BeanDescFactory { public static void clearCache() { bdCache.clear(); } - - private static boolean isProxyClass(final Class clazz) { - // JDK代理类 - return Proxy.isProxyClass(clazz) || - // cglib代理类 - clazz.getName().contains("$$"); - } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/JdkProxyUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/JdkProxyUtil.java new file mode 100644 index 000000000..6826c8055 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/JdkProxyUtil.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.reflect; + +import org.dromara.hutool.core.classloader.ClassLoaderUtil; +import org.dromara.hutool.core.lang.Assert; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Proxy; + +/** + * JDK的{@link Proxy}相关工具类封装 + * + * @author Looly + * @since 6.0.0 + */ +public class JdkProxyUtil { + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + // region ----- newProxyInstance + + /** + * 创建动态代理对象
+ * 动态代理对象的创建原理是:
+ * 假设创建的代理对象名为 $Proxy0 + * 1、根据传入的interfaces动态生成一个类,实现interfaces中的接口
+ * 2、通过传入的classloder将刚生成的类加载到jvm中。即将$Proxy0类load
+ * 3、调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法
+ * 4、将$Proxy0的实例返回给客户端。
+ * 5、当调用代理类的相应方法时,相当于调用 {@link InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])} 方法 + * + * @param 被代理对象类型 + * @param classloader 被代理类对应的ClassLoader + * @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能 + * @param interfaces 代理类中需要实现的被代理类的接口方法 + * @return 代理类 + */ + @SuppressWarnings("unchecked") + public static T newProxyInstance(final ClassLoader classloader, final InvocationHandler invocationHandler, final Class... interfaces) { + return (T) Proxy.newProxyInstance(classloader, interfaces, invocationHandler); + } + + /** + * 创建动态代理对象 + * + * @param 被代理对象类型 + * @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能 + * @param interfaces 代理类中需要实现的被代理类的接口方法 + * @return 代理类 + */ + public static T newProxyInstance(final InvocationHandler invocationHandler, final Class... interfaces) { + return newProxyInstance(ClassLoaderUtil.getClassLoader(), invocationHandler, interfaces); + } + // endregion + + // region ----- isProxy + + /** + * 是否为代理对象,判断JDK代理或Cglib代理 + * + * @param object 被检查的对象 + * @return 是否为代理对象 + */ + public static boolean isProxy(final Object object) { + Assert.notNull(object); + return isProxyClass(object.getClass()); + } + + /** + * 是否为JDK代理对象 + * + * @param object 被检查的对象 + * @return 是否为JDK代理对象 + */ + public static boolean isJdkProxy(final Object object) { + Assert.notNull(object); + return isJdkProxyClass(object.getClass()); + } + + /** + * 是否Cglib代理对象 + * + * @param object 被检查的对象 + * @return 是否Cglib代理对象 + */ + public static boolean isCglibProxy(final Object object) { + Assert.notNull(object); + return isCglibProxyClass(object.getClass()); + } + // endregion + + // region ----- isProxyClass + + /** + * 是否为代理类,判断JDK代理或Cglib代理 + * + * @param clazz 被检查的类 + * @return 是否为代理类 + */ + public static boolean isProxyClass(final Class clazz) { + return isJdkProxyClass(clazz) || isCglibProxyClass(clazz); + } + + /** + * 是否为JDK代理类 + * + * @param clazz 被检查的类 + * @return 是否为JDK代理类 + */ + public static boolean isJdkProxyClass(final Class clazz) { + return Proxy.isProxyClass(Assert.notNull(clazz)); + } + + /** + * 是否Cglib代理对象 + * + * @param clazz 被检查的对象 + * @return 是否Cglib代理对象 + */ + public static boolean isCglibProxyClass(final Class clazz) { + return Assert.notNull(clazz).getName().contains(CGLIB_CLASS_SEPARATOR); + } + + // endregion +} diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/aop/ProxyUtil.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/aop/ProxyUtil.java index 37e69c0ae..98e4cd726 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/aop/ProxyUtil.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/aop/ProxyUtil.java @@ -12,21 +12,16 @@ package org.dromara.hutool.extra.aop; -import org.dromara.hutool.core.classloader.ClassLoaderUtil; +import org.dromara.hutool.core.reflect.JdkProxyUtil; import org.dromara.hutool.extra.aop.engine.ProxyEngine; import org.dromara.hutool.extra.aop.engine.ProxyEngineFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; - /** * 代理工具类 * * @author Looly */ -public class ProxyUtil { - - private static final String CGLIB_CLASS_SEPARATOR = "$$"; +public class ProxyUtil extends JdkProxyUtil { /** * 获取动态代理引擎 @@ -60,70 +55,4 @@ public class ProxyUtil { public static T proxy(final T target, final Aspect aspect) { return getEngine().proxy(target, aspect); } - - // region ----- JDK Proxy utils - - /** - * 创建动态代理对象
- * 动态代理对象的创建原理是:
- * 假设创建的代理对象名为 $Proxy0 - * 1、根据传入的interfaces动态生成一个类,实现interfaces中的接口
- * 2、通过传入的classloder将刚生成的类加载到jvm中。即将$Proxy0类load
- * 3、调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法
- * 4、将$Proxy0的实例返回给客户端。
- * 5、当调用代理类的相应方法时,相当于调用 {@link InvocationHandler#invoke(Object, java.lang.reflect.Method, Object[])} 方法 - * - * @param 被代理对象类型 - * @param classloader 被代理类对应的ClassLoader - * @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能 - * @param interfaces 代理类中需要实现的被代理类的接口方法 - * @return 代理类 - */ - @SuppressWarnings("unchecked") - public static T newProxyInstance(final ClassLoader classloader, final InvocationHandler invocationHandler, final Class... interfaces) { - return (T) Proxy.newProxyInstance(classloader, interfaces, invocationHandler); - } - - /** - * 创建动态代理对象 - * - * @param 被代理对象类型 - * @param invocationHandler {@link InvocationHandler} ,被代理类通过实现此接口提供动态代理功能 - * @param interfaces 代理类中需要实现的被代理类的接口方法 - * @return 代理类 - */ - public static T newProxyInstance(final InvocationHandler invocationHandler, final Class... interfaces) { - return newProxyInstance(ClassLoaderUtil.getClassLoader(), invocationHandler, interfaces); - } - // endregion - - /** - * 是否为代理对象,判断JDK代理或Cglib代理 - * - * @param object 被检查的对象 - * @return 是否为代理对象 - */ - public static boolean isProxy(final Object object) { - return isJdkProxy(object) || isCglibProxy(object); - } - - /** - * 是否为JDK代理对象 - * - * @param object 被检查的对象 - * @return 是否为JDK代理对象 - */ - public static boolean isJdkProxy(final Object object) { - return Proxy.isProxyClass(object.getClass()); - } - - /** - * 是否Cglib代理对象 - * - * @param object 被检查的对象 - * @return 是否Cglib代理对象 - */ - public static boolean isCglibProxy(final Object object) { - return (object.getClass().getName().contains(CGLIB_CLASS_SEPARATOR)); - } }