demo show:
public static void main(String[] args) { //String filePath = "links\\fsx\\A.class"; String filePath = "links/fsx/A.class"; System.out.println(ClassUtils.convertResourcePathToClassName(filePath)); //links.fsx.A.class //System.out.println(ClassUtils.convertClassNameToResourcePath(filePath)); //在指定类的所属包下面,寻找一个资源文件,并返回该资源文件的文件路径 java.lang.String System.out.println(ClassUtils.addResourcePathToPackagePath(String.class, "someResource.xml")); // java/lang/someResource.xml System.out.println(ClassUtils.classPackageAsResourcePath(String.class)); //java/lang // 打印classNames System.out.println(ClassUtils.classNamesToString(String.class, Integer.class)); //[java.lang.String, java.lang.Integer] System.out.println(ClassUtils.classNamesToString(Arrays.asList(String.class, Integer.class))); //[java.lang.String, java.lang.Integer] }
public static void main(String[] args) { //String filePath = "links\\fsx\\A.class"; String filePath = "links/fsx/A.class"; System.out.println(ClassUtils.convertResourcePathToClassName(filePath)); //links.fsx.A.class //System.out.println(ClassUtils.convertClassNameToResourcePath(filePath)); //在指定类的所属包下面,寻找一个资源文件,并返回该资源文件的文件路径 java.lang.String System.out.println(ClassUtils.addResourcePathToPackagePath(String.class, "someResource.xml")); // java/lang/someResource.xml System.out.println(ClassUtils.classPackageAsResourcePath(String.class)); //java/lang // 打印classNames System.out.println(ClassUtils.classNamesToString(String.class, Integer.class)); //[java.lang.String, java.lang.Integer] System.out.println(ClassUtils.classNamesToString(Arrays.asList(String.class, Integer.class))); //[java.lang.String, java.lang.Integer] }
Demo:
public static void main(String[] args) { List<String> list = new ArrayList<>(); // 拿到该实例实现的所有的接口 System.out.println(Arrays.asList(ClassUtils.getAllInterfaces(list))); //[interface java.util.List, interface java.util.RandomAccess, interface java.lang.Cloneable, interface java.io.Serializable, interface java.util.Collection] System.out.println(ClassUtils.getAllInterfacesAsSet(list)); // 输出结果同上 }
// 这个方法很有意思:找到两个Class 的祖先类(也就是谁是父类就返回谁了) public static Class<?> determineCommonAncestor(@Nullable Class<?> clazz1, @Nullable Class<?> clazz2) {}
这个方法很有意思,Spring在Autowired自动注入AbstractAutowireCapableBeanFactory中有大量的应用:
public static void main(String[] args) { System.out.println(ClassUtils.determineCommonAncestor(Integer.class,Long.class)); //class java.lang.Number 找到他们共同父类 System.out.println(ClassUtils.determineCommonAncestor(Integer.class,Number.class)); //class java.lang.Number 若其中一个就是父类 就直接返回即可 System.out.println(ClassUtils.determineCommonAncestor(Integer.class, Person.class)); //null 八竿子打不着就返回null吧(注意相当于是Object.class 直接返回null的) }
// 是否是内部类 public static boolean isInnerClass(Class<?> clazz) { return (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())); } // 是否是CGLIB代理对象 public static boolean isCglibProxy(Object object) { return isCglibProxyClass(object.getClass()); } public static boolean isCglibProxyClass(@Nullable Class<?> clazz) { return (clazz != null && isCglibProxyClassName(clazz.getName())); } public static boolean isCglibProxyClassName(@Nullable String className) { return (className != null && className.contains(CGLIB_CLASS_SEPARATOR)); } // 获取用户定义的本来的类型,大部分情况下就是类型本身,主要针对cglib做了额外的判断,获取cglib代理之后的父类; public static Class<?> getUserClass(Object instance) {} // 获取一个对象的描述类型;一般来说,就是类名,能够正确处理数组,如果是JDK代理对象,能够正确输出其接口类型: public static String getDescriptiveType(@Nullable Object value) { ... } public static String getShortName(String className) { public static String getShortName(Class<?> clazz) { public static String getShortNameAsProperty(Class<?> clazz) { public static String getClassFileName(Class<?> clazz) { public static String getPackageName(Class<?> clazz) { public static String getPackageName(String fqClassName) { public static String getQualifiedName(Class<?> clazz) {
Demo show:
public static void main(String[] args) { System.out.println(ClassUtils.getShortName("java.lang.String")); //String System.out.println(ClassUtils.getShortName(String.class)); //String System.out.println(ClassUtils.getShortNameAsProperty(String.class)); //String System.out.println(ClassUtils.getPackageName(String.class)); //java.lang System.out.println(ClassUtils.getPackageName("java.lang.String")); //java.lang // clazz.getTypeName() System.out.println(ClassUtils.getQualifiedName(String.class)); //java.lang.String System.out.println(String.class.getName()); //java.lang.String System.out.println(String.class.getTypeName()); //java.lang.String System.out.println(ClassUtils.getDescriptiveType(ArrayList.class)); //java.lang.Class 注意此处的输出 java.lang.Class //System.out.println(ClassUtils.getDescriptiveType(getClass())); java.lang.String[] //System.out.println(ClassUtils.getDescriptiveType(new String[]{})); // com.sun.proxy.$Proxy20 implementing cn.wolfcode.springboot.utilstest.IEmployeeService, cn.wolfcode.springboot.utilstest.IAddition, org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised //System.out.println(ClassUtils.getDescriptiveType(service)); } }
public static String getQualifiedMethodName(Method method) { public static String getQualifiedMethodName(Method method, @Nullable Class<?> clazz) { public static boolean hasConstructor(Class<?> clazz, Class<?>... paramTypes) { public static <T> Constructor<T> getConstructorIfAvailable(Class<T> clazz, Class<?>... paramTypes) { //判断类是否有指定的public方法 public static boolean hasMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) { public static Method getMethod(Class<?> clazz, String methodName, @Nullable Class<?>... paramTypes) { public static Method getMethodIfAvailable(Class<?> clazz, String methodName, @Nullable Class<?>... paramTypes) { //获取指定类中匹配该方法名称的方法个数,包括非public方法; public static int getMethodCountForName(Class<?> clazz, String methodName) { //判定指定的类及其父类中是否包含指定方法名称的方法,包括非public方法; public static boolean hasAtLeastOneMethodWithName(Class<?> clazz, String methodName) { //获得最匹配的一个可以执行的方法; 和Overrid有关 public static Method getMostSpecificMethod(Method method, @Nullable Class<?> targetClass) { //该方法用于判定一个方法是否是用户可用的方法 public static boolean isUserLevelMethod(Method method) { // 桥接方法, // method. isSynthetic方法:判定一个方法是否是虚构方法(synthetic method);什么是synthetic方法?由编译器创建的,非默认构造方法 //(我们知道,类都有默认构造方法,当然重载了默认构造方法的除外,编译器都会生成一个默认构造方法的实现)在源码中没有对应的方法实现的方法都是虚构方法。 // 比如上面介绍的bridge方法就是一个典型的synthetic方法; // isGroovyObjectMethod:判定一个方法是否是Groovy的方法,因为Spring支持Groovy,而Groovy的类都实现了groovy.lang.GroovyObject类; return (method.isBridge() || (!method.isSynthetic() && !isGroovyObjectMethod(method))); } public static Method getStaticMethod(Class<?> clazz, String methodName, Class<?>... args) {
很多方法依赖于ReflectionUtils,建议使用它吧
Introspector:内省
反射:反射就是让你可以通过名称来得到对象(类,属性,方法)的技术。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值
内省:内省(Introspector) 是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法。所以它是位于Bean包下的:java.beans.Introspector,它有个方法BeanInfo bi = Introspector.getBeanInfo(demo.getClass(),Object.class);就能获取到一个BeanInfo,从而获取到每个属性值。
Struts将表单数据映射到JavaBean就是通过内省来实现的
这里面推荐两篇文章:
内省(一)之Introspector、BeanInfo、PropertyDescriptor
内省(二)之BeanUtils工具类
MethodIntrospector
// @since 4.2.3 // 定义彻底搜索元数据关联方法的算法,包括接口和父类,同时还处理参数化方法,以及接口和基于类的代理遇到的常见场景 // 通常,但不一定,用于查找带注释的处理程序方法~~~~~~~~~~~~~~ // 也就是说倘若你的注解啥的,在接口上也是可以的 public abstract class MethodIntrospector { // 核心方法:就是从指定的targetType里找到合适的方法。metadataLookup:用于过滤 public static <T> Map<Method, T> selectMethods(Class<?> targetType, final MetadataLookup<T> metadataLookup) { final Map<Method, T> methodMap = new LinkedHashMap<>(); Set<Class<?>> handlerTypes = new LinkedHashSet<>(); Class<?> specificHandlerType = null; // 如果该类型 不是JDK动态代理类型 if (!Proxy.isProxyClass(targetType)) { specificHandlerType = ClassUtils.getUserClass(targetType); handlerTypes.add(specificHandlerType); } // 拿到该目标类型所有的实现的接口们~~~~~~~ handlerTypes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetType)); // 遍历所有的需要处理的handlerTypes 然后一个个的处理 for (Class<?> currentHandlerType : handlerTypes) { // 如果找到了specificHandlerType ,那就用它,否则就是currentHandlerType final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType); // 使用的是ReflectionUtils.USER_DECLARED_METHODS 方法过滤器。 ReflectionUtils.doWithMethods(currentHandlerType, method -> { Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass); // 对这个specificMethod 还会做进一步的处理~~~~ T result = metadataLookup.inspect(specificMethod); if (result != null) { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); //================================== if (bridgedMethod == specificMethod || metadataLookup.inspect(bridgedMethod) == null) { methodMap.put(specificMethod, result); } } }, ReflectionUtils.USER_DECLARED_METHODS); } return methodMap; } public static Set<Method> selectMethods(Class<?> targetType, final ReflectionUtils.MethodFilter methodFilter) { return selectMethods(targetType, (MetadataLookup<Boolean>) method -> (methodFilter.matches(method) ? Boolean.TRUE : null)).keySet(); } public static Method selectInvocableMethod(Method method, Class<?> targetType) { if (method.getDeclaringClass().isAssignableFrom(targetType)) { return method; } try { String methodName = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); for (Class<?> ifc : targetType.getInterfaces()) { try { return ifc.getMethod(methodName, parameterTypes); } catch (NoSuchMethodException ex) { // Alright, not on this interface then... } } // A final desperate attempt on the proxy class itself... return targetType.getMethod(methodName, parameterTypes); } catch (NoSuchMethodException ex) { throw new IllegalStateException(String.format( "Need to invoke method '%s' declared on target class '%s', " + "but not found in any interface(s) of the exposed proxy type. " + "Either pull the method up to an interface or switch to CGLIB " + "proxies by enforcing proxy-target-class mode in your configuration.", method.getName(), method.getDeclaringClass().getSimpleName())); } } @FunctionalInterface public interface MetadataLookup<T> { @Nullable T inspect(Method method); } }
它的使用还是非常多得:
示例代码:
// 处理@EventListener注解 annotatedMethods = MethodIntrospector.selectMethods(targetType, (MethodIntrospector.MetadataLookup<EventListener>) method -> AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class)); // 处理@Scheduled和@Schedules注解 Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> { Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);