【小家Spring】Spring Framework提供的实用纯Java工具类大合集(二)(上)

简介: 【小家Spring】Spring Framework提供的实用纯Java工具类大合集(二)(上)

前言


接着上一篇

【小家Spring】Spring Framework提供的实用纯Java工具类大合集(一)


继续来介绍Spring提供的好用的一些工具类。


Assert


这是Spring提供给我们的断言工具,是以抛异常的方式来处理的。

若你是自己的书写框架的时候,可以使用它的,而不用自己各种去if判空了


    public static void main(String[] args) {
        Integer param = 1;
        Assert.state(param == 2, "param的值不为2,请校对~");
        //Assert.hasText();
        //Assert.hasLength();
        //Assert.notNull();
        //Assert.notEmpty();
        //...
    }
// 输出
Exception in thread "main" java.lang.IllegalStateException: param的值不为2,请校对~

ClassUtils:非常非常重要的一个工具类


这是关于类级别相关的工具类,虽然只是提供给Spring框架内部使用,但是很多方法还是有一定使用价值,并且理解这些方法的实现,也是有一定价值的


该工具类在Spring框架中可谓使用非常广泛


首先ClassUtils是一个非常大的工具类,提供了很多缓存数据和初始化内容

public abstract class ClassUtils {
  // 这些常量 挺重要的  都是public的  我们也可以使用   这些都遵循了Java的命名规范
  public static final String ARRAY_SUFFIX = "[]";
  private static final String INTERNAL_ARRAY_PREFIX = "[";
  // 这个非常有意思:如果你是八大基本类型(PRIMITIVE类型)的数组类型, toString()方法是"[A"/"[B"...等等
  // 但是如果你是new Person[0]或者new Object[0]这种数组类型,全都是"[L"打头得,这个非常有规律性
  private static final String NON_PRIMITIVE_ARRAY_PREFIX = "[L";
  private static final char PACKAGE_SEPARATOR = '.';
  private static final char PATH_SEPARATOR = '/';
  // 是否是内部类
  private static final char INNER_CLASS_SEPARATOR = '$';
  // 这个符号,用来判断是否是CGLIB的代理类
  public static final String CGLIB_CLASS_SEPARATOR = "$$";
  public static final String CLASS_FILE_SUFFIX = ".class";
  // 下面这个很重要,提高效率必备---缓存   他们都是private的
  // 缓存八大基本数据类型 --> 包装类型的映射 所有长度相同
  private static final Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new IdentityHashMap<>(8);
  // 和上面区别:上面的key是这里的value
  private static final Map<Class<?>, Class<?>> primitiveTypeToWrapperMap = new IdentityHashMap<>(8);
  // 保存所遇的基础数据类型 8 + 8(对应数组类型) + void.class 一共会有17个元素
  private static final Map<String, Class<?>> primitiveTypeNameMap = new HashMap<>(32);
  // 顾名思义:它是缓存一些常用的Class类型。key为class.getName()  value为Class本身
  // 比如:上面所列的17个、 还有包装类型的数组(8个) + Number.class/Class.class... + Enum.class/Exception.class/ List.clss... 总之就是缓存比较常用的一些类型吧
  private static final Map<String, Class<?>> commonClassCache = new HashMap<>(64);
  // 缓存Java语言的一些常用接口:
  //Serializable.class, Externalizable.class, Closeable.class, AutoCloseable.class, Cloneable.class, Comparable.class
  private static final Set<Class<?>> javaLanguageInterfaces;
  // 这个方法非常常用:按照获取当前线程上下文类加载器-->获取当前类类加载器-->获取系统启动类加载器的顺序来获取
  @Nullable
  public static ClassLoader getDefaultClassLoader() {
    ClassLoader cl = null;
    try {
      cl = Thread.currentThread().getContextClassLoader();
    }
    catch (Throwable ex) {
      // Cannot access thread context ClassLoader - falling back...
    }
    if (cl == null) {
      // No thread context class loader -> use class loader of this class.
      cl = ClassUtils.class.getClassLoader();
      if (cl == null) {
        // getClassLoader() returning null indicates the bootstrap ClassLoader
        try {
          cl = ClassLoader.getSystemClassLoader();
        }
        catch (Throwable ex) {
          // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
        }
      }
    }
    return cl;
  }
  //这个方法较为简单,使用传入的classloader替换线程的classloader;使用场景,比如一个线程的classloader和spring的classloader不一致的时候,就可以使用这个方法替换
  @Nullable
  public static ClassLoader overrideThreadContextClassLoader(@Nullable ClassLoader classLoaderToUse) {
    Thread currentThread = Thread.currentThread();
    ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
    if (classLoaderToUse != null && !classLoaderToUse.equals(threadContextClassLoader)) {
      currentThread.setContextClassLoader(classLoaderToUse);
      return threadContextClassLoader;
    }
    else {
      return null;
    }
  }
  // 看名字就知道,是Class.forName的一个增强版本;通过指定的classloader加载对应的类;除了能正常加载普通的类型,``还能加载简单类型,数组,或者内部类``
  // 数组是通过Array.newInstance创建出来的,然后.getClass()
  public static Class<?> forName(String name, @Nullable ClassLoader classLoader){
    ...
  }
}


看下测试代码:


  //可以看到,简单类型int,数组String[]和内部类(内部类通过父类.子类的方式即可获取)
    public static void main(String[] args) throws ClassNotFoundException {
        ClassLoader defaultClassLoader = ClassUtils.getDefaultClassLoader();
        // 加载基本数据类型int都可议
        System.out.println(ClassUtils.forName("int", defaultClassLoader)); // int
        System.out.println(ClassUtils.forName("java.lang.String[]", defaultClassLoader)); //class [Ljava.lang.String;
        System.out.println(ClassUtils.forName("java.lang.Thread.State", defaultClassLoader)); //class java.lang.Thread$State
    }
  //和forName方法相同,内部就是直接调用的forName方法,只是抛出的异常不一样而已;
  public static Class<?> resolveClassName(String className, @Nullable ClassLoader classLoader){
    ...
  }
  // 这个在Spring里也有大量的应用:判断某个是否存在  内部依赖于forName()方法 下面写个Demo
  public static boolean isPresent(String className, @Nullable ClassLoader classLoader) { ... }
  // 专门处理基本类型  效率非常的高
  public static Class<?> resolvePrimitiveClassName(String name) {
      Class<?> result = null;
      // 简单类型,最长值不要超过8,如果超过8,反而可以忽略了
      if (name != null && name.length() <= 8) {
          // Could be a primitive - likely.
          result = primitiveTypeNameMap.get(name);
      }
    return result;
  //判断一个类型是否在指定类加载器中可见  它在下面方法`getAllInterfacesForClassAsSet`会有用到
  boolean isVisible(Class<?> clazz, ClassLoader classLoader)
}


给个Demo如下:


    public static void main(String[] args) throws ClassNotFoundException {
        ClassLoader defaultClassLoader = ClassUtils.getDefaultClassLoader();
        System.out.println(ClassUtils.isPresent("java.lang.String", defaultClassLoader)); //true
        System.out.println(ClassUtils.isPresent("java.lang.xxx", defaultClassLoader)); //false
        System.out.println(ClassUtils.resolvePrimitiveClassName("int")); //int
        System.out.println(ClassUtils.resolvePrimitiveClassName("aaa")); //null  如果不存在,就返回null
        // 这里以defaultClassLoader为例
        System.out.println(ClassUtils.isVisible(String.class, defaultClassLoader)); // true
    }
  //判定一个类是否是简单类型的包装类;
  boolean isPrimitiveWrapper(Class<?> clazz);
  // 基本类型或者包装类型
  boolean isPrimitiveOrWrapper(Class<?> clazz)
  // 基本类型的数组类型
  public static boolean isPrimitiveArray(Class<?> clazz);
  // 基本类型的包装类型的数组类型
  public static boolean isPrimitiveWrapperArray(Class<?> clazz);
  //如果传入的类型是一个简单类型,返回这个简单类型的包装类型
  public static Class<?> resolvePrimitiveIfNecessary(Class<?> clazz);


demo演示:


    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println(ClassUtils.isPrimitiveWrapper(Integer.class)); //true
        System.out.println(ClassUtils.isPrimitiveWrapper(int.class)); //false
        System.out.println(ClassUtils.isPrimitiveOrWrapper(int.class)); //true
        System.out.println(ClassUtils.isPrimitiveArray(Integer[].class)); //false
        System.out.println(ClassUtils.isPrimitiveArray(int[].class)); // true
        System.out.println(ClassUtils.isPrimitiveWrapperArray(int[].class)); //false
        // 传进去事包装类型  最终返回的是基本类型
        Class<?> clazz = ClassUtils.resolvePrimitiveIfNecessary(Integer[].class);
        System.out.println(clazz); //class [Ljava.lang.Integer;
        System.out.println(Integer[].class); //class [Ljava.lang.Integer;
        System.out.println(clazz == Integer[].class); //true
    }


  public static boolean isAssignable(Class<?> lhsType, Class<?> rhsType) { ... }
  public static boolean isAssignableValue(Class<?> type, @Nullable Object value) { ... }


demo演示:

    public static void main(String[] args) {
        System.out.println(Object.class.isAssignableFrom(Integer.class)); // true
        System.out.println(Object.class.isAssignableFrom(int.class)); // false  请注意这里返回的是false
        // 但是下面这么弄  就都返回true了
        System.out.println(ClassUtils.isAssignable(Object.class, Integer.class)); //true
        System.out.println(ClassUtils.isAssignable(Object.class, int.class)); // true
        // 有个更简便的方式 对象参与比较
        Integer i = 0;
        System.out.println(ClassUtils.isAssignableValue(Object.class, i)); //true
    }


  public static String convertResourcePathToClassName(String resourcePath) {}
  public static String convertClassNameToResourcePath(String className) {}
  //在指定类的所属包下面,寻找一个资源文件,并返回该资源文件的文件路径
  public static String addResourcePathToPackagePath(Class<?> clazz, String resourceName) {}
  public static String classPackageAsResourcePath(@Nullable Class<?> clazz) {}
  public static String classNamesToString(Class<?>... classes) {}
  public static String classNamesToString(@Nullable Collection<Class<?>> classes) {}
相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
93 2
|
4天前
|
Java Spring
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
41 15
|
1天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
66 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
2月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
254 12
基于开源框架Spring AI Alibaba快速构建Java应用
|
3月前
|
Java 数据库连接 开发者
Spring 框架:Java 开发者的春天
【10月更文挑战第27天】Spring 框架由 Rod Johnson 在 2002 年创建,旨在解决 Java 企业级开发中的复杂性问题。它通过控制反转(IOC)和面向切面的编程(AOP)等核心机制,提供了轻量级的容器和丰富的功能,支持 Web 开发、数据访问等领域,显著提高了开发效率和应用的可维护性。Spring 拥有强大的社区支持和丰富的生态系统,是 Java 开发不可或缺的工具。
|
3月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
145 2
|
2月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
57 0
|
2月前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
49 0
|
7月前
|
Java
排名前16的Java工具类
排名前16的Java工具类
46 0
下一篇
开通oss服务