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)
获取一个类型的所有接口;