ClassUtils类

1,368 阅读3分钟

ClassLoader getDefaultClassLoader()

该方法用于获取默认的类加载器;方法功能很明确,平时也用的比较多,可能平时我们要获取类加载器,就一个class.getClassLoader()就完了,我们来看看spring是如何考虑的:

public static ClassLoader getDefaultClassLoader() {
    ClassLoader cl = null;
    try {
        //获取当前线程上下文类加载器
        cl = Thread.currentThread().getContextClassLoader();
    }catch (Throwable ex) {
    }
    if (cl == null) {
        // 如果没有context loader,使用当前类的类加载器;
        cl = ClassUtils.class.getClassLoader();
        if (cl == null) {
            // 如果当前类加载器无法获取,获得bootstrap ClassLoader系统启动类加载器
            try {
                cl = ClassLoader.getSystemClassLoader();
            } catch (Throwable ex) {
            }
        }
    }
    return cl;
}

1,通过Thread.getContextClassLoader()方法获取到的是线程绑定的类加载器,这个classloader是父线程在创建子线程的时候,通过Thread.setContextClassLoader()方法设置进去,用于该线程加载类和资源的,如果没有调用这个方法,那么直接使用父线程的classLoader;如果这个方法返回null,代表该线程直接使用的系统class loader或者bootstrap class loader;

2,几种类加载器的层级关系简单说明:

bootstrap class loader:主要负责main方法启动的时候,加载JAVA_HOME/lib下的jar包;

extension class loader:主要负责加载JAVA_HOME/ext/lib下的jar包;

system class loader:主要负责加载classpath下的jar包或者类;

这里只需要明白,system class loader是比bootstrap class loader离我们应用更近;而除了bootstrap class loader,其他几个class loader都继承了Classloader类

在一个正常应用中,类获取到的classloader就是system class loader;而extention class loader是不一样的;

public static ClassLoader overrideThreadContextClassLoader(@Nullable ClassLoader classLoaderToUse)

这个方法较为简单,使用传入的classloader替换线程的classloader;使用场景,比如一个线程的classloader和spring的classloader不一致的时候,就可以使用这个方法替换;

Class<?> forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError

看名字就知道,是Class.forName的一个增强版本;通过指定的classloader加载对应的类;除了能正常加载普通的类型,还能加载简单类型,数组,或者内部类,测试代码:

@Test
public void testClassforName() throws Exception{
    System.out.println(ClassUtils.forName("int",ClassUtils.getDefaultClassLoader()));
    System.out.println(ClassUtils.forName("java.lang.String[]",ClassUtils.getDefaultClassLoader()));
    System.out.println(ClassUtils.forName("java.lang.Thread.State",ClassUtils.getDefaultClassLoader()));
}
//打印结果
int
class [Ljava.lang.String;
class java.lang.Thread$State

Class<?> resolveClassName(String className, ClassLoader classLoader) throws IllegalArgumentException

和forName方法相同,内部就是直接调用的forName方法,只是抛出的异常不一样而已;

Class<?> resolvePrimitiveClassName(String name)

获取简单类型的类;这个方法是用于处理forName方法中简单类型的调用方法; System.out.println(ClassUtils.resolvePrimitiveClassName(“int”));

打印:int

         static {
		primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
		primitiveWrapperTypeMap.put(Byte.class, byte.class);
		primitiveWrapperTypeMap.put(Character.class, char.class);
		primitiveWrapperTypeMap.put(Double.class, double.class);
		primitiveWrapperTypeMap.put(Float.class, float.class);
		primitiveWrapperTypeMap.put(Integer.class, int.class);
		primitiveWrapperTypeMap.put(Long.class, long.class);
		primitiveWrapperTypeMap.put(Short.class, short.class);
		primitiveWrapperTypeMap.put(Void.class, void.class);

		// Map entry iteration is less expensive to initialize than forEach with lambdas
		for (Map.Entry<Class<?>, Class<?>> entry : primitiveWrapperTypeMap.entrySet()) {
			primitiveTypeToWrapperMap.put(entry.getValue(), entry.getKey());
			registerCommonClasses(entry.getKey());
		}

		Set<Class<?>> primitiveTypes = new HashSet<>(32);
		//就是把简单类型对应的名字和类型直接放到primitiveTypeNameMap中
		primitiveTypes.addAll(primitiveWrapperTypeMap.values());
		Collections.addAll(primitiveTypes, boolean[].class, byte[].class, char[].class,
				double[].class, float[].class, int[].class, long[].class, short[].class);
		primitiveTypes.add(void.class);
		for (Class<?> primitiveType : primitiveTypes) {
			primitiveTypeNameMap.put(primitiveType.getName(), primitiveType);
		}
		

String getQualifiedMethodName(Method method):获取方法的全名,包括类的权限定名.方法名;

Method getMethod(Class clazz, String methodName, Class… paramTypes)

得到类上指定的public方法;其实现也是一个标准的反射使用:

Class[] getAllInterfacesForClass(Class clazz)

获取一个类型的所有接口;