Обучение использованию собственных классов инструментов Spring

задняя часть Spring
Обучение использованию собственных классов инструментов Spring

Большинство наших проектов основаны на архитектуре Spring.Сам Spring содержит много полезных классов инструментов.Обучение использованию этих классов инструментов не только позволяет нам добиться вдвое большего результата с половиной усилий,но и сокращает введение ненужных дополнительных классов инструментов . При просмотре исходного кода этих классов инструментов обнаруживается, что все они являются абстрактными типами, потому что методы классов инструментов обычно являются статическими статическими методами, статическими методами и привязками классов, которые можно использовать после загрузки класса без создания экземпляра. (просто абстрактный. Классы не могут быть созданы напрямую и могут определять неабстрактные методы), поэтому более уместно определить служебный класс как абстрактный.

Метод печати в этой статье является инкапсуляцией System.out.println:

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

ClassUtils

org.springframework.util.classUtilsсодержит некоторые иjava.lang.ClassСвязанные служебные методы.

getDefaultClassLoader

ClassLoader getDefaultClassLoader()Получите загрузчик классов текущего контекста потока:

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

overrideThreadContextClassLoader

ClassLoader overrideThreadContextClassLoader(@Nullable ClassLoader classLoaderToUse)Переопределите загрузчик классов текущего контекста потока с помощью определенного загрузчика классов:

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)Возвращает экземпляр класса по имени класса, аналогично Class.forName(), но более мощное и может использоваться для примитивных типов, внутренних классов и т. д.:

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)Определите, содержит ли текущий classLoader целевой тип (включая все его родительские классы и интерфейсы):

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

resolvePrimitiveClassName

Class<?> resolvePrimitiveClassName(@Nullable String name)Получить исходный класс по заданному имени класса:

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

isPrimitiveWrapper

boolean isPrimitiveWrapper(Class<?> clazz)Определите, является ли данный класс классом-оболочкой, таким как Boolean, Byte, Character, Short, Integer, Long, Float, Double или 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

Аналогичные методы такжеisPrimitiveOrWrapperОпределите, является ли это примитивным классом или классом-оболочкой,isPrimitiveWrapperArrayОпределите, является ли это массивом классов-оболочек,isPrimitiveArrayОпределяет, является ли массив примитивным классом.

resolvePrimitiveIfNecessary

Class<?> resolvePrimitiveIfNecessary(Class<?> clazz)Если данный класс является исходным классом, верните соответствующий класс-оболочку, в противном случае верните данный класс напрямую:

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)Проверьте, может ли rhsType быть назначен lhsType путем отражения (обратите внимание, что тип оболочки может быть назначен соответствующему примитивному типу, механизм автоматической распаковки):

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)Проверьте, соответствует ли данное значение заданному типу:

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)Преобразуйте путь к классам в полное имя класса:

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

на самом деле/заменить..convertClassNameToResourcePathМетод работает наоборот.

classNamesToString

String classNamesToString(Class<?>... classes)Посмотрите прямо на демо без объяснений:

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)Возвращает набор типов интерфейса, реализованных данным объектом экземпляра:

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

Аналогичные методы такжеgetAllInterfacesForClass,getAllInterfacesAsSet,getAllInterfacesForClassAsSet

determineCommonAncestor

Class<?> determineCommonAncestor(@Nullable Class<?> clazz1, @Nullable Class<?> clazz2)Найдите общего предка данного типа (так называемый общий предок относится к данному типу, вызывающемуclass.getSuperclassПолученный общий тип, если заданный тип Object.class, interface, примитивный тип или Void, возвращает null напрямую):

// 它两都是接口
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)Определите, является ли данный тип внутренним классом (нестатическим):

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

boolean isCglibProxy(Object object)Это прокси-объект Cglib:

@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

Возвращает false, если класс конфигурации не проксируется Cglib:

@SpringBootApplication
public class AopApplication {

    @Configuration(proxyBeanMethods = false) // 注意这里
    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

Однако этот метод устарел, рекомендуется использоватьorg.springframework.aop.support.AopUtils.isCglibProxy(Object)метод.

getUserClass

Class<?> getUserClass(Object instance)Возвращает тип, соответствующий данному экземпляру.Если экземпляр является прокси-объектом Cglib, он возвращает тип целевого прокси-объекта:

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

Пример прокси Cglib:

@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(myConfigure.getClass());
        System.out.println(ClassUtils.getUserClass(myConfigure));
    }
}
class cc.mrbird.aop.AopApplication$MyConfigure$$EnhancerBySpringCGLIB$$e51ce45
class cc.mrbird.aop.AopApplication$MyConfigure

matchesTypeName

boolean matchesTypeName(Class<?> clazz, @Nullable String typeName)Проверьте, совпадают ли заданные имена классов и типов:

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

getShortName

String getShortName(Class<?> clazz)Вернуть имя класса:

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

getShortNameAsProperty

String getShortNameAsProperty(Class<?> clazz)Верните имя класса с первой строчной буквой, если это внутренний класс, удалите имя внешнего класса:

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

getClassFileName

String getClassFileName(Class<?> clazz)Вернуть имя класса + .class:

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

getPackageName

String getPackageName(Class<?> clazz)Имя возвращаемого пакета:

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

getQualifiedName

String getQualifiedName(Class<?> clazz)Возвращает полное имя класса с [] в конце, если это тип массива:

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

getQualifiedMethodName

String getQualifiedMethodName(Method method)Получите полное имя метода:

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

hasConstructor

boolean hasConstructor(Class<?> clazz, Class<?>... paramTypes)Проверьте, есть ли у данного типа конструктор с заданным параметром типа:

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)Возвращает конструктор данного типа параметра для данного типа или null, если нет:

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)Проверьте, имеет ли данный тип указанный метод:

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

перегруженный методboolean hasMethod(Class<?> clazz, String methodName, Class<?>... paramTypes).

getMethod

Method getMethod(Class<?> clazz, String methodName, @Nullable Class<?>... paramTypes)Найдите указанный метод из указанного типа и создайте исключение 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)

Если вы хотите вернуть null вместо того, чтобы генерировать исключение, если оно не найдено, вы можете использоватьgetMethodIfAvailableметод.

getMethodCountForName

int getMethodCountForName(Class<?> clazz, String methodName)Найдите количество методов указанного типа по имени метода (учитываются переопределение, перегрузка и непубличность):

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

Аналогичные методы такжеhasAtLeastOneMethodWithName, должен быть хотя бы один.

getStaticMethod

Method getStaticMethod(Class<?> clazz, String methodName, Class<?>... args)Получить статический метод заданного типа или null, если метод не статический или такого метода нет:

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

FileSystemUtils

Служебный класс файловой системы

deleteRecursively

boolean deleteRecursively(@Nullable File root)Рекурсивно удаляет указанный файл или каталог, возвращает true, если удаление прошло успешно, и false, если не удалось, и исключение не выдается.

Каталог удаления утилиты File пытается удалить каталог a:

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

Поскольку каталог a содержит подкаталоги (файлы), следует использовать рекурсивное удаление:

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

перегруженный методboolean deleteRecursively(@Nullable Path root)По функциям аналогичен этому методу, но этот метод может вызывать исключения ввода-вывода.

copyRecursively

void copyRecursively(File src, File dest)Рекурсивно скопируйте файл src в dest (целевой путь будет создан автоматически, если он не существует):

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

перегруженный методvoid copyRecursively(Path src, Path dest).

StreamUtils

Служебные методы, содержащие некоторые файловые потоки, имеют размер буфера по умолчанию 4096 байт.

Уведомление: Все методы этого класса инструментов не закроют поток!