001/* 002 * Copyright (c) 2023-2026, Agents-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.agentsflex.core.util; 017 018import java.lang.reflect.*; 019import java.util.ArrayList; 020import java.util.Arrays; 021import java.util.List; 022import java.util.function.Predicate; 023 024/** 025 * 类实例创建者创建者 026 * 027 * @author michael 028 * @date 17/3/21 029 */ 030public class ClassUtil { 031 032 private ClassUtil() { 033 } 034 035 private static final String[] OBJECT_METHODS = new String[]{ 036 "toString", 037 "getClass", 038 "equals", 039 "hashCode", 040 "wait", 041 "notify", 042 "notifyAll", 043 "clone", 044 "finalize" 045 }; 046 047 //proxy frameworks 048 private static final List<String> PROXY_CLASS_NAMES = Arrays.asList("net.sf.cglib.proxy.Factory" 049 // cglib 050 , "org.springframework.cglib.proxy.Factory" 051 052 // javassist 053 , "javassist.util.proxy.ProxyObject" 054 , "org.apache.ibatis.javassist.util.proxy.ProxyObject"); 055 private static final String ENHANCER_BY = "$$EnhancerBy"; 056 private static final String JAVASSIST_BY = "_$$_"; 057 058 public static boolean isProxy(Class<?> clazz) { 059 for (Class<?> cls : clazz.getInterfaces()) { 060 if (PROXY_CLASS_NAMES.contains(cls.getName())) { 061 return true; 062 } 063 } 064 //java proxy 065 return Proxy.isProxyClass(clazz); 066 } 067 068 private static <T> Class<T> getJdkProxySuperClass(Class<T> clazz) { 069 final Class<?> proxyClass = Proxy.getProxyClass(clazz.getClassLoader(), clazz.getInterfaces()); 070 return (Class<T>) proxyClass.getInterfaces()[0]; 071 } 072 073 public static <T> Class<T> getUsefulClass(Class<T> clazz) { 074 if (isProxy(clazz)) { 075 return getJdkProxySuperClass(clazz); 076 } 077 078 //ControllerTest$ServiceTest$$EnhancerByGuice$$40471411#hello -------> Guice 079 //com.demo.blog.Blog$$EnhancerByCGLIB$$69a17158 ----> CGLIB 080 //io.jboot.test.app.TestAppListener_$$_jvstb9f_0 ------> javassist 081 final String name = clazz.getName(); 082 if (name.contains(ENHANCER_BY) || name.contains(JAVASSIST_BY)) { 083 return (Class<T>) clazz.getSuperclass(); 084 } 085 086 return clazz; 087 } 088 089 090 public static Class<?> getWrapType(Class<?> clazz) { 091 if (clazz == null || !clazz.isPrimitive()) { 092 return clazz; 093 } 094 if (clazz == Integer.TYPE) { 095 return Integer.class; 096 } else if (clazz == Long.TYPE) { 097 return Long.class; 098 } else if (clazz == Boolean.TYPE) { 099 return Boolean.class; 100 } else if (clazz == Float.TYPE) { 101 return Float.class; 102 } else if (clazz == Double.TYPE) { 103 return Double.class; 104 } else if (clazz == Short.TYPE) { 105 return Short.class; 106 } else if (clazz == Character.TYPE) { 107 return Character.class; 108 } else if (clazz == Byte.TYPE) { 109 return Byte.class; 110 } else if (clazz == Void.TYPE) { 111 return Void.class; 112 } 113 return clazz; 114 } 115 116 117 public static boolean isArray(Class<?> clazz) { 118 return clazz.isArray() 119 || clazz == int[].class 120 || clazz == long[].class 121 || clazz == short[].class 122 || clazz == float[].class 123 || clazz == double[].class; 124 } 125 126 127 public static List<Field> getAllFields(Class<?> clazz) { 128 List<Field> fields = new ArrayList<>(); 129 doGetFields(clazz, fields, null, false); 130 return fields; 131 } 132 133 public static List<Field> getAllFields(Class<?> clazz, Predicate<Field> predicate) { 134 List<Field> fields = new ArrayList<>(); 135 doGetFields(clazz, fields, predicate, false); 136 return fields; 137 } 138 139 public static Field getFirstField(Class<?> clazz, Predicate<Field> predicate) { 140 List<Field> fields = new ArrayList<>(); 141 doGetFields(clazz, fields, predicate, true); 142 return fields.isEmpty() ? null : fields.get(0); 143 } 144 145 private static void doGetFields(Class<?> clazz, List<Field> fields, Predicate<Field> predicate, boolean firstOnly) { 146 if (clazz == null || clazz == Object.class) { 147 return; 148 } 149 150 Field[] declaredFields = clazz.getDeclaredFields(); 151 for (Field declaredField : declaredFields) { 152 if (predicate == null || predicate.test(declaredField)) { 153 fields.add(declaredField); 154 if (firstOnly) { 155 break; 156 } 157 } 158 } 159 160 if (firstOnly && !fields.isEmpty()) { 161 return; 162 } 163 164 doGetFields(clazz.getSuperclass(), fields, predicate, firstOnly); 165 } 166 167 public static List<Method> getAllMethods(Class<?> clazz) { 168 List<Method> methods = new ArrayList<>(); 169 doGetMethods(clazz, methods, null, false); 170 return methods; 171 } 172 173 public static List<Method> getAllMethods(Class<?> clazz, Predicate<Method> predicate) { 174 List<Method> methods = new ArrayList<>(); 175 doGetMethods(clazz, methods, predicate, false); 176 return methods; 177 } 178 179 public static Method getFirstMethod(Class<?> clazz, Predicate<Method> predicate) { 180 List<Method> methods = new ArrayList<>(); 181 doGetMethods(clazz, methods, predicate, true); 182 return methods.isEmpty() ? null : methods.get(0); 183 } 184 185 186 private static void doGetMethods(Class<?> clazz, List<Method> methods, Predicate<Method> predicate, boolean firstOnly) { 187 if (clazz == null || clazz == Object.class) { 188 return; 189 } 190 191 Method[] declaredMethods = clazz.getDeclaredMethods(); 192 for (Method method : declaredMethods) { 193 if (predicate == null || predicate.test(method)) { 194 methods.add(method); 195 if (firstOnly) { 196 break; 197 } 198 } 199 } 200 201 if (firstOnly && !methods.isEmpty()) { 202 return; 203 } 204 205 doGetMethods(clazz.getSuperclass(), methods, predicate, firstOnly); 206 } 207 208}