001/** 002 * Copyright (c) 2022-2023, Mybatis-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.mybatisflex.core.util; 017 018 019import java.lang.reflect.*; 020import java.util.ArrayList; 021import java.util.Arrays; 022import java.util.List; 023import java.util.function.Predicate; 024 025/** 026 * 类实例创建者创建者 027 * Created by michael on 17/3/21. 028 */ 029public class ClassUtil { 030 031 //proxy frameworks 032 private static final List<String> PROXY_CLASS_NAMES = Arrays.asList("net.sf.cglib.proxy.Factory" 033 // cglib 034 , "org.springframework.cglib.proxy.Factory" 035 036 // javassist 037 , "javassist.util.proxy.ProxyObject" 038 , "org.apache.ibatis.javassist.util.proxy.ProxyObject"); 039 040 public static boolean isProxy(Class<?> clazz) { 041 for (Class<?> cls : clazz.getInterfaces()) { 042 if (PROXY_CLASS_NAMES.contains(cls.getName())) { 043 return true; 044 } 045 } 046 //java proxy 047 return Proxy.isProxyClass(clazz); 048 } 049 050 private static final String ENHANCER_BY = "$$EnhancerBy"; 051 private static final String JAVASSIST_BY = "_$$_"; 052 053 public static <T> Class<T> getUsefulClass(Class<T> clazz) { 054 if (isProxy(clazz)) { 055 return (Class<T>) clazz.getSuperclass(); 056 } 057 058 //ControllerTest$ServiceTest$$EnhancerByGuice$$40471411#hello -------> Guice 059 //com.demo.blog.Blog$$EnhancerByCGLIB$$69a17158 ----> CGLIB 060 //io.jboot.test.app.TestAppListener_$$_jvstb9f_0 ------> javassist 061 062 final String name = clazz.getName(); 063 if (name.contains(ENHANCER_BY) || name.contains(JAVASSIST_BY)) { 064 return (Class<T>) clazz.getSuperclass(); 065 } 066 067 return clazz; 068 } 069 070 071 public static Class<?> wrap(Class<?> clazz) { 072 if (clazz == null || !clazz.isPrimitive()) { 073 return clazz; 074 } 075 if (clazz == Integer.TYPE) { 076 return Integer.class; 077 } else if (clazz == Long.TYPE) { 078 return Long.class; 079 } else if (clazz == Boolean.TYPE) { 080 return Boolean.class; 081 } else if (clazz == Float.TYPE) { 082 return Float.class; 083 } else if (clazz == Double.TYPE) { 084 return Double.class; 085 } else if (clazz == Short.TYPE) { 086 return Short.class; 087 } else if (clazz == Character.TYPE) { 088 return Character.class; 089 } else if (clazz == Byte.TYPE) { 090 return Byte.class; 091 } else if (clazz == Void.TYPE) { 092 return Void.class; 093 } 094 return clazz; 095 } 096 097 098 public static boolean isArray(Class<?> clazz) { 099 return clazz.isArray() 100 || clazz == int[].class 101 || clazz == long[].class 102 || clazz == short[].class 103 || clazz == float[].class 104 || clazz == double[].class; 105 } 106 107 108 public static <T> T newInstance(Class<T> clazz) { 109 try { 110 Constructor<?> defaultConstructor = null; 111 Constructor<?> otherConstructor = null; 112 113 Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors(); 114 for (Constructor<?> constructor : declaredConstructors) { 115 if (constructor.getParameterCount() == 0) { 116 defaultConstructor = constructor; 117 } else if (Modifier.isPublic(constructor.getModifiers())) { 118 otherConstructor = constructor; 119 } 120 } 121 if (defaultConstructor != null) { 122 return (T) defaultConstructor.newInstance(); 123 } else if (otherConstructor != null) { 124 Class<?>[] parameterTypes = otherConstructor.getParameterTypes(); 125 Object[] parameters = new Object[parameterTypes.length]; 126 for (int i = 0; i < parameterTypes.length; i++) { 127 if (parameterTypes[i].isPrimitive()) { 128 parameters[i] = ConvertUtil.getPrimitiveDefaultValue(parameterTypes[i]); 129 } else { 130 parameters[i] = null; 131 } 132 } 133 return (T) otherConstructor.newInstance(parameters); 134 } 135 throw new IllegalArgumentException("the class \"" + clazz.getName() + "\" has no constructor."); 136 } catch (Exception e) { 137 throw new RuntimeException("Can not newInstance class: " + clazz.getName()); 138 } 139 } 140 141 142 public static <T> T newInstance(Class<T> clazz, Object... paras) { 143 try { 144 Constructor<?>[] constructors = clazz.getDeclaredConstructors(); 145 for (Constructor<?> constructor : constructors) { 146 if (isMatchedParas(constructor, paras)) { 147 Object ret = constructor.newInstance(paras); 148 return (T) ret; 149 } 150 } 151 throw new IllegalArgumentException("Can not find constructor by paras: \"" + Arrays.toString(paras) + "\" in class[" + clazz.getName() + "]"); 152 } catch (Exception e) { 153 e.printStackTrace(); 154 } 155 156 return null; 157 } 158 159 160 private static boolean isMatchedParas(Constructor<?> constructor, Object[] paras) { 161 if (constructor.getParameterCount() == 0) { 162 return paras == null || paras.length == 0; 163 } 164 165 if (constructor.getParameterCount() > 0 166 && (paras == null || paras.length != constructor.getParameterCount())) { 167 return false; 168 } 169 170 Class<?>[] parameterTypes = constructor.getParameterTypes(); 171 for (int i = 0; i < parameterTypes.length; i++) { 172 Class<?> parameterType = parameterTypes[i]; 173 Object paraObject = paras[i]; 174 if (paraObject != null && !parameterType.isAssignableFrom(paraObject.getClass())) { 175 return false; 176 } 177 } 178 179 return true; 180 } 181 182 183 public static List<Field> getAllFields(Class<?> cl) { 184 List<Field> fields = new ArrayList<>(); 185 doGetFields(cl, fields, null); 186 return fields; 187 } 188 189 public static List<Field> getAllFields(Class<?> cl, Predicate<Field> predicate) { 190 List<Field> fields = new ArrayList<>(); 191 doGetFields(cl, fields, predicate); 192 return fields; 193 } 194 195 private static void doGetFields(Class<?> cl, List<Field> fields, Predicate<Field> predicate) { 196 if (cl == null || cl == Object.class) { 197 return; 198 } 199 200 Field[] declaredFields = cl.getDeclaredFields(); 201 for (Field declaredField : declaredFields) { 202 if (predicate == null || predicate.test(declaredField)) { 203 fields.add(declaredField); 204 } 205 } 206 207 doGetFields(cl.getSuperclass(), fields, predicate); 208 } 209 210 public static List<Method> getAllMethods(Class<?> cl) { 211 List<Method> methods = new ArrayList<>(); 212 doGetMethods(cl, methods, null); 213 return methods; 214 } 215 216 public static List<Method> getAllMethods(Class<?> cl, Predicate<Method> predicate) { 217 List<Method> methods = new ArrayList<>(); 218 doGetMethods(cl, methods, predicate); 219 return methods; 220 } 221 222 223 private static void doGetMethods(Class<?> cl, List<Method> methods, Predicate<Method> predicate) { 224 if (cl == null || cl == Object.class) { 225 return; 226 } 227 228 Method[] declaredMethods = cl.getDeclaredMethods(); 229 for (Method method : declaredMethods) { 230 if (predicate == null || predicate.test(method)) { 231 methods.add(method); 232 } 233 } 234 235 doGetMethods(cl.getSuperclass(), methods, predicate); 236 } 237 238}