/** * Copyright (c) 2015, biezhi 王爵 (biezhi.me@gmail.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.blade.kit.reflect; import com.blade.kit.Emptys; import com.blade.kit.ExceptionKit; import com.blade.kit.StringKit; import com.blade.kit.SystemKit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.lang.reflect.*; import java.net.JarURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * 有关 Reflection处理的工具类。 * * 这个类中的每个方法都可以“安全”地处理 <code>null</code> ,而不会抛出 <code>NullPointerException</code>。 * * @author <a href="mailto:biezhi.me@gmail.com">biezhi</a> * @since 1.0 */ public abstract class ReflectKit { private static final Logger LOGGER = LoggerFactory.getLogger(ReflectKit.class); /** 新建对象 * @throws IllegalAccessException * @throws InstantiationException * @throws ClassNotFoundException */ public static Object newInstance(String className) { Object obj = null; try { Class<?> clazz = Class.forName(className); obj = clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } LOGGER.debug("New {}", className); return obj; } /** * 创建一个实例对象 * @param clazz class对象 * @return * @throws IllegalAccessException * @throws InstantiationException */ public static Object newInstance(Class<?> clazz) { try { return clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 根据类名获取Class对象 * * @param className 类名称 * @return 返回Class对象 */ public static Class<?> newClass(String className){ try { return Class.forName(className); } catch (ClassNotFoundException e) { } return null; } /** * 获取包是否存在 * * @param packageName 包名称 * @return 返回包是否存在 */ public static boolean isPackage(String packageName){ if(StringKit.isNotBlank(packageName)){ Package temp = Package.getPackage(packageName); return null != temp; } return false; } public static boolean isClass(String className){ if(StringKit.isNotBlank(className)){ try { Class.forName(className); return true; } catch (ClassNotFoundException e) { } } return false; } /** * 创建一个实例对象 * @param clazz class对象 * @return * @throws IllegalAccessException * @throws InstantiationException */ public static <T> T newBean(Class<T> clazz) { try { Object object = clazz.newInstance(); return clazz.cast(object); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; } /** 用setter设置bean属性 * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static void setProperty(Object bean, String name, Object value) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { String methodName = "set" + StringKit.firstUpperCase(name); invokeMehodByName(bean, methodName, value); } /** 用getter获取bean属性 * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static Object getProperty(Object bean, String name) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { String methodName = "get" + StringKit.firstUpperCase(name); return invokeMehodByName(bean, methodName); } /** 类型转换 */ @SuppressWarnings("unchecked") public static <T> T cast(Object value, Class<T> type) { if (value != null && !type.isAssignableFrom(value.getClass())) { if (is(type, int.class, Integer.class)) { value = Integer.parseInt(String.valueOf(value)); } else if (is(type, long.class, Long.class)) { value = Long.parseLong(String.valueOf(value)); } else if (is(type, float.class, Float.class)) { value = Float.parseFloat(String.valueOf(value)); } else if (is(type, double.class, Double.class)) { value = Double.parseDouble(String.valueOf(value)); } else if (is(type, boolean.class, Boolean.class)) { value = Boolean.parseBoolean(String.valueOf(value)); } else if (is(type, String.class)) { value = String.valueOf(value); } } return (T) value; } /** 查找方法 */ public static Method getMethodByName(Object classOrBean, String methodName) { Method ret = null; if (classOrBean != null) { Class<?> clazz = null; if (classOrBean instanceof Class<?>) { clazz = (Class<?>) classOrBean; } else { clazz = classOrBean.getClass(); } for (Method method : clazz.getMethods()) { if (method.getName().equals(methodName)) { ret = method; break; } } } return ret; } public static Method getMethodByName(Class<?> clazz, String methodName) { Method ret = null; for (Method method : clazz.getMethods()) { if (method.getName().equals(methodName)) { ret = method; break; } } return ret; } /*private static boolean sameType(Type[] types, Class<?>[] clazzes) { if (types.length != clazzes.length) { return false; } for (int i = 0; i < types.length; i++) { if (!Type.getType(clazzes[i]).equals(types[i])) { return false; } } return true; } public static String[] getMethodParamsNames(final Method m) { try { final String[] paramNames = new String[m.getParameterTypes().length]; Class<?> declaringClass = m.getDeclaringClass(); String className = declaringClass.getName(); int lastDotIndex = className.lastIndexOf("."); InputStream is = declaringClass.getResourceAsStream(className.substring(lastDotIndex + 1) + ".class"); ClassReader cr = new ClassReader(is); cr.accept(new ClassVisitor(Opcodes.ASM4) { @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { final Type[] args = Type.getArgumentTypes(desc); // 方法名相同并且参数个数相同 if (!name.equals(m.getName()) || !sameType(args, m.getParameterTypes())) { return super.visitMethod(access, name, desc, signature, exceptions); } MethodVisitor v = super.visitMethod(access, name, desc, signature, exceptions); return new MethodVisitor(Opcodes.ASM4, v) { @Override public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { int i = index - 1; // 如果是静态方法,则第一就是参数 // 如果不是静态方法,则第一个是"this",然后才是方法的参数 if (Modifier.isStatic(m.getModifiers())) { i = index; } if (i >= 0 && i < paramNames.length) { paramNames[i] = name; } super.visitLocalVariable(name, desc, signature, start, end, index); } }; } }, 0); return paramNames; } catch (SecurityException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }*/ /** * * @param bean 类实例 * @param methodName 方法名称 * @param args 方法参数 * @return * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static Object invokeMehodByName(Object bean, String methodName, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method method = getMethodByName(bean, methodName); Class<?>[] types = method.getParameterTypes(); int argCount = args == null ? 0 : args.length; // 参数个数对不上 ExceptionKit.makeRunTimeWhen(argCount != types.length, "%s in %s", methodName, bean); // 转参数类型 for (int i = 0; i < argCount; i++) { args[i] = cast(args[i], types[i]); } return method.invoke(bean, args); } /** * * @param bean 类实例 * @param method 方法名称 * @param args 方法参数 * @return * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static Object invokeMehod(Object bean, Method method, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class<?>[] types = method.getParameterTypes(); int argCount = args == null ? 0 : args.length; // 参数个数对不上 ExceptionKit.makeRunTimeWhen(argCount != types.length, "%s in %s", method.getName(), bean); // 转参数类型 for (int i = 0; i < argCount; i++) { args[i] = cast(args[i], types[i]); } return method.invoke(bean, args); } // ------------------------------------------------------ /** 对象是否其中一个 */ public static boolean is(Object obj, Object... mybe) { if (obj != null && mybe != null) { for (Object mb : mybe) if (obj.equals(mb)) return true; } return false; } public static boolean isNot(Object obj, Object... mybe) { return !is(obj, mybe); } // ------------------------------------------------------ /** 扫描包下面所有的类 */ public static List<String> scanPackageClass(String rootPackageName) { List<String> classNames = new ArrayList<String>(); try { ClassLoader loader = ReflectKit.class.getClassLoader(); URL url = loader.getResource(rootPackageName.replace('.', '/')); ExceptionKit.makeRunTimeWhen(url == null, "package[%s] not found!", rootPackageName); String protocol = url.getProtocol(); if ("file".equals(protocol)) { LOGGER.debug("Scan in file ..."); File[] files = new File(url.toURI()).listFiles(); for (File f : files) { scanPackageClassInFile(rootPackageName, f, classNames); } } else if ("jar".equals(protocol)) { LOGGER.debug("Scan in jar ..."); JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile(); scanPackageClassInJar(jar, rootPackageName, classNames); } } catch (URISyntaxException e) { } catch (IOException e) { } return classNames; } /** 扫描文件夹下所有class文件 */ private static void scanPackageClassInFile(String rootPackageName, File rootFile, List<String> classNames) { String absFileName = rootPackageName + "." + rootFile.getName(); if (rootFile.isFile() && absFileName.endsWith(".class")) { classNames.add(absFileName.substring(0, absFileName.length() - 6)); } else if (rootFile.isDirectory()) { String tmPackageName = rootPackageName + "." + rootFile.getName(); for (File f : rootFile.listFiles()) { scanPackageClassInFile(tmPackageName, f, classNames); } } } /** * 扫描jar里面的类 * @param jar jar包文件 * @param packageDirName 包目录 * @param classNames class名称列表 */ private static void scanPackageClassInJar(JarFile jar, String packageDirName, List<String> classNames) { Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName().replace('/', '.'); if (name.startsWith(packageDirName) && name.endsWith(".class")) { classNames.add(name.substring(0, name.length() - 6)); } } } /** * 方法调用,如果<code>clazz</code>为<code>null</code>,返回<code>null</code>; * <p> * 如果<code>method</code>为<code>null</code>,返回<code>null</code> * <p> * 如果<code>target</code>为<code>null</code>,则为静态方法 * * @param method 调用的方法 * @param target 目标对象 * @param args 方法的参数值 * @return 调用结果 * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static Object invokeMethod(Method method, Object target, Object...args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (method == null) { return null; } method.setAccessible(true); return method.invoke(target, args); } /** * <p> * 调用一个命名的方法,其参数类型相匹配的对象类型。 * </p> * * * @param object 调用方法作用的对象 * @param methodName 方法名 * @param args 参数值 * @param parameterTypes 参数类型 * @return 调用的方法的返回值 * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * */ public static Object invokeMethod(Object object, String methodName, Object[] args, Class<?>...parameterTypes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (object == null || StringKit.isEmpty(methodName)) { return null; } if (parameterTypes == null) { parameterTypes = Emptys.EMPTY_CLASS_ARRAY; } if (args == null) { args = Emptys.EMPTY_OBJECT_ARRAY; } Method method; try { method = object.getClass().getDeclaredMethod(methodName, parameterTypes); } catch (Exception ex) { throw ExceptionKit.toRuntimeException(ex); } if (method == null) { return null; } return invokeMethod(method, object, args); } /** * <p> * 调用一个命名的静态方法,其参数类型相匹配的对象类型。 * </p> * * * @param clazz 调用方法作用的类 * @param methodName 方法名 * @param args 参数值 * @param parameterTypes 参数类型 * @return 调用的方法的返回值 * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException * */ public static Object invokeStaticMethod(Class<?> clazz, String methodName, Object[] args, Class<?>...parameterTypes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (parameterTypes == null) { parameterTypes = Emptys.EMPTY_CLASS_ARRAY; } if (args == null) { args = Emptys.EMPTY_OBJECT_ARRAY; } Method method; try { method = clazz.getDeclaredMethod(methodName, parameterTypes); } catch (Exception ex) { throw ExceptionKit.toRuntimeException(ex); } if (method == null) { return null; } return invokeMethod(method, null, args); } // ========================================================================== // 辅助方法。 // ========================================================================== private static final Method IS_SYNTHETIC; static { Method isSynthetic = null; if (SystemKit.getJavaInfo().isJavaVersionAtLeast(1.5f)) { // cannot call synthetic methods: try { isSynthetic = Member.class.getMethod("isSynthetic", Emptys.EMPTY_CLASS_ARRAY); } catch (Exception e) { // ignore } } IS_SYNTHETIC = isSynthetic; } public static boolean isAccessible(Member m) { return m != null && Modifier.isPublic(m.getModifiers()) && !isSynthetic(m); } static boolean isSynthetic(Member m) { if (IS_SYNTHETIC != null) { try { return ((Boolean) IS_SYNTHETIC.invoke(m, (Object[]) null)).booleanValue(); } catch (Exception e) { } } return false; } /** * Check whether the {@link Class} identified by the supplied name is present. * * @param className the name of the class to check * @return true if class is present, false otherwise */ public static boolean isPresent(String className) { try { // what's wrong with old plain Class.forName // this code supposed to work everywhere including containers Class.forName(className); // getClassLoader().loadClass(className); return true; } catch (Throwable ex) { return false; } } public static boolean isPublic(Member m) { return m != null && Modifier.isPublic(m.getModifiers()); } public static void forceAccess(AccessibleObject object) { if (object == null || object.isAccessible()) { return; } try { object.setAccessible(true); } catch (SecurityException e) { throw ExceptionKit.toRuntimeException(e); } } public static boolean hasInterface(Class<?> type, Class<?> interfaceType) { if(null != type && null != interfaceType){ Class<?>[] interfaces = type.getInterfaces(); if(null != interfaces && interfaces.length > 0){ for(Class<?> inte : interfaces){ if(inte == interfaceType){ return true; } } } } return false; } }