Learning how to use Spring's own tool classes

Posted by Chamza on Mon, 20 Sep 2021 22:00:51 +0200

Most of our projects are based on spring architecture. Spring itself contains many practical tool classes. Learning the use of these tool classes can not only achieve twice the result with half the effort, but also reduce the introduction of unnecessary additional tool classes. When you view the source code of these tool classes, you can find that they are of abstract type. This is because the methods of tool classes are generally static static methods. Static methods and classes are bound and can be used after loading. There is no need to instantiate them (just because the abstract class cannot be instantiated directly, and non abstract methods can be defined), so it is very appropriate to define the tool class as abstract type.

The print method in this article is the encapsulation of System.out.println:

private static void print(Object value) {
    System.out.println(value);
}

ClassUtils

org.springframework.util.classUtils contains some practical methods related to java.lang.Class.

getDefaultClassLoader

ClassLoader getDefaultClassLoader() gets the classloader of the current thread context:

print(ClassUtils.getDefaultClassLoader());
sun.misc.Launcher$AppClassLoader@18b4aac2

overrideThreadContextClassLoader

ClassLoader overrideThreadContextClassLoader(@Nullable ClassLoader classLoaderToUse) overrides the classloader of the current thread context with a specific classloader:

print(ClassUtils.getDefaultClassLoader());
ClassUtils.overrideThreadContextClassLoader(ClassLoader.getSystemClassLoader().getParent());
print(ClassUtils.getDefaultClassLoader());
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@3feba861

forName

forName(String name, @Nullable ClassLoader classLoader) returns a class instance through the class name, which is similar to Class.forName(), but has stronger functions. It can be used for original types, internal classes, etc

ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
print(ClassUtils.forName("int", classLoader));
print(ClassUtils.forName("java.lang.String[]", classLoader));
print(ClassUtils.forName("java.lang.Thread$State", classLoader));
int
class [Ljava.lang.String;
class java.lang.Thread$State

isPresent

boolean isPresent(String className, @Nullable ClassLoader classLoader) determines whether the current classLoader contains the target type (including all its parent classes and interfaces):

ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
print(ClassUtils.isPresent("int", classLoader));
print(ClassUtils.isPresent("intt", classLoader));
true
false

resolvePrimitiveClassName

Class<?> Resolveprimitiveclassname (@ nullable string name) gets the original class from the given class name:

print(ClassUtils.resolvePrimitiveClassName("int"));
print(ClassUtils.resolvePrimitiveClassName("java.lang.Integer"));
int
null

isPrimitiveWrapper

Boolean isprimitivewrapper (class <? > clazz) determines whether a given class is a wrapper class, such as Boolean, Byte, Character, Short, Integer, Long, Float, Double or Void:

print(ClassUtils.isPrimitiveWrapper(Integer.class));
print(ClassUtils.isPrimitiveWrapper(Character.class));
print(ClassUtils.isPrimitiveWrapper(Void.class));
print(ClassUtils.isPrimitiveWrapper(String.class));
true
true
true
false

Similar methods include isPrimitiveOrWrapper to judge whether it is the original class or wrapper class, isPrimitiveWrapperArray to judge whether it is the wrapper class array, and isPrimitiveArray to judge whether it is the original class array.

resolvePrimitiveIfNecessary

Class<?> Resolveprimitiveifnecessary (class <? > clazz) if the given class is the original class, the corresponding wrapper class is returned; otherwise, the given class is returned directly:

print(ClassUtils.resolvePrimitiveIfNecessary(int.class));
print(ClassUtils.resolvePrimitiveIfNecessary(Object.class));
class java.lang.Integer
class java.lang.Object

isAssignable

Boolean isassignable (class <? > lhsType, class <? > rhsType) checks whether rhsType can be assigned to lhsType through reflection (note that the packaging type can be assigned to the corresponding original type, and the automatic box disassembly mechanism):

print(ClassUtils.isAssignable(Integer.class, int.class));
print(ClassUtils.isAssignable(Object.class, String.class));
print(ClassUtils.isAssignable(BeanPostProcessor.class, InstantiationAwareBeanPostProcessor.class));
print(ClassUtils.isAssignable(double.class, Double.class)); // consider this
print(ClassUtils.isAssignable(Integer.class, Long.class));
true
true
true
true
false

isAssignableValue

Boolean isassignablevalue (class <? > type, @ nullable object value) determines whether the given value conforms to the given type:

print(ClassUtils.isAssignableValue(Integer.class, 1));
print(ClassUtils.isAssignableValue(Integer.class, 1L));
print(ClassUtils.isAssignableValue(int.class, Integer.valueOf(1)));
print(ClassUtils.isAssignableValue(Object.class,1));
print(ClassUtils.isAssignableValue(String.class,1));
true
false
true
true
false

convertResourcePathToClassName

String convertResourcePathToClassName(String resourcePath) converts a classpath to a fully qualified class name:

print(ClassUtils.convertResourcePathToClassName("java/lang/String"));
java.lang.String

It's actually replacing / with. The convertClassNameToResourcePath method does the opposite.

classNamesToString

String classnamestostring (class <? >... Classes) see the demo directly without explanation:

print(ClassUtils.classNamesToString(String.class, Integer.class, BeanPostProcessor.class));
[java.lang.String, java.lang.Integer, org.springframework.beans.factory.config.BeanPostProcessor]

getAllInterfaces

Class<?> [] getallinterfaces (object instance) returns a collection of interface types implemented by a given instance object:

AutowiredAnnotationBeanPostProcessor processor = new AutowiredAnnotationBeanPostProcessor();
Class<?>[] allInterfaces = ClassUtils.getAllInterfaces(processor);
Arrays.stream(allInterfaces).forEach(System.out::println);
interface org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
interface org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor
interface org.springframework.core.PriorityOrdered
interface org.springframework.beans.factory.BeanFactoryAware

Similar methods include getAllInterfacesForClass, getAllInterfacesAsSet and getallinterfacesforclassassset

determineCommonAncestor

Class<?> Determinecommonancessor (@ nullable class <? > clazz1, @ nullable class <? > clazz2) finds the common ancestor of a given type (the so-called common ancestor refers to the common type obtained by calling class.getSuperclass for a given type. If the given type is Object.class, interface, original type or Void, null is returned directly):

// Both are interfaces
print(ClassUtils.determineCommonAncestor(AutowireCapableBeanFactory.class, ListableBeanFactory.class));
print(ClassUtils.determineCommonAncestor(Long.class, Integer.class));
print(ClassUtils.determineCommonAncestor(String.class, Integer.class));
null
class java.lang.Number
null

isInnerClass

Boolean isinnerclass (class <? > clazz) determines whether a given type is an internal class (non static):

class A {
     class B {
         
    }
}
print(ClassUtils.isInnerClass(A.B.class)); // true
static class A {
    class B {

    }
}
print(ClassUtils.isInnerClass(A.B.class)); // true
static class A {
    static class B {

    }
}
print(ClassUtils.isInnerClass(A.B.class)); // false

isCglibProxy

Whether boolean isCglibProxy(Object object) is a Cglib proxy object:

@SpringBootApplication
public class AopApplication {

    @Configuration
    static class MyConfigure {

    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(AopApplication.class, args);
        MyConfigure myConfigure = context.getBean(MyConfigure.class);
        System.out.println(ClassUtils.isCglibProxy(myConfigure));
    }
}
true

If the configuration class is not represented by Cglib, the return is false:

@SpringBootApplication
public class AopApplication {

    @Configuration(proxyBeanMethods = false) // Pay attention here
    static class MyConfigure {

    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(AopApplication.class, args);
        MyConfigure myConfigure = context.getBean(MyConfigure.class);
        System.out.println(ClassUtils.isCglibProxy(myConfigure));
    }
}
false

However, this method is obsolete. It is recommended to use the org. Springframework. AOP. Support. Aoutils. Iscglibproxy (object) method.

getUserClass

Class<?> Getuserclass (object instance) returns the type corresponding to a given instance. If the instance is an object after Cglib proxy, the target object type of the proxy is returned:

print(ClassUtils.getUserClass("Hello")); // class java.lang.String

Cglib agent example:

@SpringBootApplication
public class AopApplication {

    @Configuration
    static class MyConfigure {

    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(AopApplication.class, args);
        MyConfigure myConfigure = context.getBean(MyConfigure.class);
        // Pay attention to their differences
        System.out.println(myConfigure.getClass());
        System.out.println(ClassUtils.getUserClass(myConfigure));
    }
}
class cc.mrbird.aop.AopApplication$MyConfigure$$EnhancerBySpringCGLIB$$e51ce45
class cc.mrbird.aop.AopApplication$MyConfigure

matchesTypeName

Boolean matchstypename (class <? > clazz, @ nullable string typename) determines whether the given class and type name match:

print(ClassUtils.matchesTypeName(String.class, "java.lang.String")); // true

getShortName

String getshortname (class <? > clazz) returns the class name:

print(ClassUtils.getShortName(String.class)); // String

getShortNameAsProperty

String getshortnameasproperty (class <? > clazz) returns the lowercase class name. If it is an internal class, remove the external class name:

print(ClassUtils.getShortNameAsProperty(String.class)); // string
class A {
    class B {
    }
}
print(ClassUtils.getShortNameAsProperty(String.class)); // b

getClassFileName

String getclassfilename (class <? > clazz) returns the class name +. Class:

print(ClassUtils.getShortNameAsProperty(String.class)); // String.class

getPackageName

String getpackagename (class <? > clazz) returns the package name:

print(ClassUtils.getShortNameAsProperty(String.class)); // java.lang

getQualifiedName

String getqualifiedname (class <? > clazz) returns the fully qualified class name. If it is an array type, add []:

print(ClassUtils.getQualifiedName(String.class));
print(ClassUtils.getQualifiedName(String[].class));
java.lang.String
java.lang.String[]

getQualifiedMethodName

String getqualifiedmethodname (method) gets the fully qualified name of the method:

print(ClassUtils.getQualifiedMethodName(
        ClassUtils.class.getDeclaredMethod("getQualifiedMethodName", Method.class
        )));
org.springframework.util.ClassUtils.getQualifiedMethodName

hasConstructor

Boolean hasconstructor (class <? > clazz, class <? >... Paramtypes) determines whether a given type has a given type parameter constructor:

print(ClassUtils.hasConstructor(String.class, String.class));
print(ClassUtils.hasConstructor(String.class, Object.class));
true
false

getConstructorIfAvailable

<T> Constructor < T > getconstructorifavailable (class < T > clazz, class <? >... Paramtypes) returns the constructor of the given parameter type of the given type. If not, null is returned:

Constructor<String> constructorIfAvailable = ClassUtils.getConstructorIfAvailable(String.class, String.class);
print(constructorIfAvailable != null);
print(constructorIfAvailable.toString());
true
public java.lang.String(java.lang.String)

hasMethod

Boolean hasmethod (class <? > clazz, method method) determines whether a given type has a specified method:

Method hasMethod = ClassUtils.class.getDeclaredMethod("hasMethod", Class.class, Method.class);
print(ClassUtils.hasMethod(ClassUtils.class, hasMethod)); // true

Overloaded method Boolean hasmethod (class <? > clazz, string methodname, class <? >... Paramtypes).

getMethod

Method getmethod (class <? > clazz, string methodname, @ nullable class <? >... Paramtypes) found the specified method from the specified type, but found no exception throwing IllegalStateException:

ClassUtils.getMethod(ClassUtils.class,"hello", String.class);
java.lang.IllegalStateException: Expected method not found: java.lang.NoSuchMethodException: org.springframework.util.ClassUtils.hello(java.lang.String)

If you want to return null without throwing an exception, you can use the getMethodIfAvailable method.

getMethodCountForName

Int getmethodcountforname (class <? > clazz, string methodname) finds the number of methods from the specified type through the method name (override, overload and non-public are counted):

print(ClassUtils.getMethodCountForName(ClassUtils.class,"hasMethod")); // 2

A similar method is hasAtLeastOneMethodWithName, which must have at least one.

getStaticMethod

Method getstaticmethod (class <? > clazz, string methodname, class <? >... Args) gets the static method of the given type. If the method is not static or does not have this method, null is returned:

Method method = ClassUtils.getStaticMethod(ClassUtils.class, "getDefaultClassLoader");
print(method != null);
print(method.getReturnType());
true
class java.lang.ClassLoader

FileSystemUtils

File System utility class

deleteRecursively

boolean deleteRecursively(@Nullable File root) recursively deletes the specified file or directory. true will be returned if the deletion is successful, false will be returned if it fails, and no exception will be thrown.

Delete directory of utility File attempt to delete a directory:

File file = new File("a");
print(file.delete()); // false

Because directory a contains subdirectories (files), recursive deletion should be used:

File file = new File("a");
print(FileSystemUtils.deleteRecursively(file)); // true

The overloaded method boolean deleteRecursively(@Nullable Path root) has similar functions to this method, but this method may throw IO exceptions.

copyRecursively

void copyRecursively(File src, File dest) recursively copies src files to DeST (automatically created if the target path does not exist):

File src = new File("a");
File dest = new File("aa");
FileSystemUtils.copyRecursively(src, dest);

Overload the method void copyRecursively(Path src, Path dest).

StreamUtils

Contains some practical methods for file streams. The default buffer size is 4096 bytes.

Note: all methods of this tool class will not be closed!

Topics: Java Spring Back-end