Spring 5 ContextTypeMatchClassLoader 源码分析

ContextTypeMatchClassLoader :覆盖ClassLoader的特殊变体,用于AbstractApplicationContext中的临时类型匹配。 为每个loadClass调用从缓存的字节数组中重新定义类,以便在父类ClassLoader中拾取 最近加载的类型。

ContextTypeMatchClassLoader

/**
 * Special variant of an overriding ClassLoader, used for temporary type
 * matching in {@link AbstractApplicationContext}. Redefines classes from
 * a cached byte array for every {@code loadClass} call in order to
 * pick up recently loaded types in the parent ClassLoader.
 * <p>覆盖ClassLoader的特殊变体,用于{@link AbstractApplicationContext}中的临时类型匹配。
 * 为每个{@code loadClass}调用从缓存的字节数组中重新定义类,以便在父类ClassLoader中拾取
 * 最近加载的类型</p>
 * @author Juergen Hoeller
 * @since 2.5
 * @see AbstractApplicationContext
 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#setTempClassLoader
 */
class ContextTypeMatchClassLoader extends DecoratingClassLoader implements SmartClassLoader {
    
    

	static {
    
    
		//https://www.jianshu.com/p/8210e891f564,
		// 通过该方法,可以使得ClassLoader执行并行加载机制,提高加载效率。
		ClassLoader.registerAsParallelCapable();
	}


	private static Method findLoadedClassMethod;

	static {
    
    
		try {
    
    
			findLoadedClassMethod = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class);
		}
		catch (NoSuchMethodException ex) {
    
    
			throw new IllegalStateException("Invalid [java.lang.ClassLoader] class: no 'findLoadedClass' method defined!");
		}
	}


	/** Cache for byte array per class name. */
	private final Map<String, byte[]> bytesCache = new ConcurrentHashMap<>(256);


	public ContextTypeMatchClassLoader(@Nullable ClassLoader parent) {
    
    
		super(parent);
	}

	@Override
	public Class<?> loadClass(String name) throws ClassNotFoundException {
    
    
		//使用ContextOverridingClassLoader对象加载指定的类对象
		//ContextOverridingClassLoader:用于为每个加载的类创建ClassLoader。
		//			缓存文件内容,但为每个调用重新定义类
		return new ContextOverridingClassLoader(getParent()).loadClass(name);
	}

	@Override
	public boolean isClassReloadable(Class<?> clazz) {
    
    
		//如果该类的类加载器是ContextOverridingClassLoader对象,则返回true,
		// 	表示该类可重载(在此ClassLoader中)
		return (clazz.getClassLoader() instanceof ContextOverridingClassLoader);
	}


	/**
	 * ClassLoader to be created for each loaded class.
	 * Caches class file content but redefines class for each call.
	 * <p>用于为每个加载的类创建ClassLoader。缓存文件内容,但为每个调用
	 * 重新定义类</p>
	 */
	private class ContextOverridingClassLoader extends OverridingClassLoader {
    
    

		public ContextOverridingClassLoader(ClassLoader parent) {
    
    
			super(parent);
		}

		@Override
		protected boolean isEligibleForOverriding(String className) {
    
    
			//如果该className需要排除 或者 是 ContextTypeMatchClassLoader需要排除的
			if (isExcluded(className) || ContextTypeMatchClassLoader.this.isExcluded(className)) {
    
    
				//返回false,表示className不适合该类加载器加载
				return false;
			}
			//使findLoadedClass方法对象变成可访问
			ReflectionUtils.makeAccessible(findLoadedClassMethod);
			//获取父级类加载器
			ClassLoader parent = getParent();
			//循环获取每层的父类加载器
			while (parent != null) {
    
    
				//使用父类加载器反射执行'findLoadedClass'方法,以判断给className是否加载过
				if (ReflectionUtils.invokeMethod(findLoadedClassMethod, parent, className) != null) {
    
    
					//加载过的,返回false,表示className不适合该类加载器加载
					return false;
				}
				parent = parent.getParent();
			}
			//默认情况,返回false,表示该className适合该类加载器加载
			return true;
		}

		@Override
		protected Class<?> loadClassForOverriding(String name) throws ClassNotFoundException {
    
    
			//从字节缓存中获取name对应的字节数组
			byte[] bytes = bytesCache.get(name);
			//如果存在
			if (bytes == null) {
    
    
				//加载name的定义字节
				bytes = loadBytesForClass(name);
				//如果字节不为null
				if (bytes != null) {
    
    
					//将字节缓存起来
					bytesCache.put(name, bytes);
				}
				else {
    
    
					return null;
				}
			}
			根据字节构建类对象
			return defineClass(name, bytes, 0, bytes.length);
		}
	}

}

OverridingClassLoader

/**
 * {@code ClassLoader} that does <i>not</i> always delegate to the parent loader
 * as normal class loaders do. This enables, for example, instrumentation to be
 * forced in the overriding ClassLoader, or a "throwaway" class loading behavior
 * where selected application classes are temporarily loaded in the overriding
 * {@code ClassLoader} for introspection purposes before eventually loading an
 * instrumented version of the class in the given parent {@code ClassLoader}.
 * <p>{@code ClassLoader}并不总是想普通的类加载器一样委托给父加载器。例如这使得可以
 * 覆盖的ClassLoader中强制执行检查,或者执行'丢弃'类的加载行为。在此行为中,处于自省目的,
 * 以进行自省,然后最终将类的检查版本加载到给定的父级的ClassLoader</p>
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 2.0.1
 */
public class OverridingClassLoader extends DecoratingClassLoader {
    
    

	/**
	 * Packages that are excluded by default.
	 * <p>默认情况下排除的软件包。</p>
	 * */
	public static final String[] DEFAULT_EXCLUDED_PACKAGES = new String[]
			{
    
    "java.", "javax.", "sun.", "oracle.", "javassist.", "org.aspectj.", "net.sf.cglib."};

	private static final String CLASS_FILE_SUFFIX = ".class";

	static {
    
    
		//https://www.jianshu.com/p/8210e891f564,
		// 通过该方法,可以使得ClassLoader执行并行加载机制,提高加载效率。
		ClassLoader.registerAsParallelCapable();
	}


	@Nullable
	private final ClassLoader overrideDelegate;


	/**
	 * Create a new OverridingClassLoader for the given ClassLoader.
	 * @param parent the ClassLoader to build an overriding ClassLoader for
	 */
	public OverridingClassLoader(@Nullable ClassLoader parent) {
    
    
		this(parent, null);
	}

	/**
	 * Create a new OverridingClassLoader for the given ClassLoader.
	 * @param parent the ClassLoader to build an overriding ClassLoader for
	 * @param overrideDelegate the ClassLoader to delegate to for overriding
	 * @since 4.3
	 */
	public OverridingClassLoader(@Nullable ClassLoader parent, @Nullable ClassLoader overrideDelegate) {
    
    
		super(parent);
		this.overrideDelegate = overrideDelegate;
		for (String packageName : DEFAULT_EXCLUDED_PACKAGES) {
    
    
			excludePackage(packageName);
		}
	}


	@Override
	public Class<?> loadClass(String name) throws ClassNotFoundException {
    
    
		if (this.overrideDelegate != null && isEligibleForOverriding(name)) {
    
    
			return this.overrideDelegate.loadClass(name);
		}
		return super.loadClass(name);
	}

	//reslove为true时,会对指定类优先执行链接功能。默认情况下是false
	//ClassLoad的链接功能会调用resolveClass(Class<?>),
	@Override
	protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    
    
		if (isEligibleForOverriding(name)) {
    
    
			Class<?> result = loadClassForOverriding(name);
			if (result != null) {
    
    
				if (resolve) {
    
    
					resolveClass(result);
				}
				return result;
			}
		}
		return super.loadClass(name, resolve);
	}

	/**
	 * Determine whether the specified class is eligible for overriding
	 * by this class loader.
	 * <p>确定指定的类是否适合该类加载器加载</p>
	 * @param className the class name to check
	 * @return whether the specified class is eligible
	 * @see #isExcluded
	 */
	protected boolean isEligibleForOverriding(String className) {
    
    
		//只要没有添加到 excludedPackages 或 excludedClasses的类都适合加载
		return !isExcluded(className);
	}

	/**
	 * Load the specified class for overriding purposes in this ClassLoader.
	 * <p>在此ClassLoader中加载指定的类以进行覆盖</p>
	 * <p>The default implementation delegates to {@link #findLoadedClass},
	 * {@link #loadBytesForClass} and {@link #defineClass}.
	 * <p>默认实现将委托给{@link #findLoadedClass},{@link #loadBytesForClass},和
	 * {@link #defineClass}</p>
	 * @param name the name of the class - 类名
	 * @return the Class object, or {@code null} if no class defined for that name
	 * - Class对象,如果没有为该名称定义任何类,则为{@code null}
	 * @throws ClassNotFoundException if the class for the given name couldn't be loaded
	 * - 如果给定名称的类无法加载
	 */
	@Nullable
	protected Class<?> loadClassForOverriding(String name) throws ClassNotFoundException {
    
    
		//看看该类名是否已经加载过
		Class<?> result = findLoadedClass(name);
		//如果没有加载过
		if (result == null) {
    
    
			//加载给定类名的字节
			byte[] bytes = loadBytesForClass(name);
			//如果加载成功
			if (bytes != null) {
    
    
				//根据字节构建类对象
				result = defineClass(name, bytes, 0, bytes.length);
			}
		}
		return result;
	}

	/**
	 * Load the defining bytes for the given class,
	 * to be turned into a Class object through a {@link #defineClass} call.
	 * <p>加载给定类的定义字节,以通过defineClass调用将其转换为Class对象</p>
	 * <p>The default implementation delegates to {@link #openStreamForClass}
	 * and {@link #transformIfNecessary}.
	 * <p>默认实现将委托给{@link #openStreamForClass}和{@link #transformIfNecessary}</p>
	 * @param name the name of the class - 类名
	 * @return the byte content (with transformers already applied),
	 * or {@code null} if no class defined for that name
	 * - 字节内容(已经应用了转换器),如果没有该名称定义类,则为{@code null}
	 * @throws ClassNotFoundException if the class for the given name couldn't be loaded
	 * - 如果给定名称的类无法加载
	 */
	@Nullable
	protected byte[] loadBytesForClass(String name) throws ClassNotFoundException {
    
    
		//打开指定类的InputStream。默认实现通过父ClassLoader的getResourceAsStream方法加载标准类文件。
		InputStream is = openStreamForClass(name);
		//如果输入流打不开,返回null
		if (is == null) {
    
    
			return null;
		}
		try {
    
    
			// Load the raw bytes. - 记载原始字节
			byte[] bytes = FileCopyUtils.copyToByteArray(is);
			// Transform if necessary and use the potentially transformed bytes.
			//必须是进行转换,并使用转换后的字节,钩子方法,默认直接返回参数bytes
			return transformIfNecessary(name, bytes);
		}
		catch (IOException ex) {
    
    
			throw new ClassNotFoundException("Cannot load resource for class [" + name + "]", ex);
		}
	}

	/**
	 * Open an InputStream for the specified class.
	 * <p>打开指定类的InputStream。</p>
	 * <p>The default implementation loads a standard class file through
	 * the parent ClassLoader's {@code getResourceAsStream} method.
	 * <p>默认实现通过父ClassLoader的getResourceAsStream方法加载标准类文件。</p>
	 * @param name the name of the class - 类名
	 * @return the InputStream containing the byte code for the specified class
	 * - 包含指定类的字节码的InputStream
	 */
	@Nullable
	protected InputStream openStreamForClass(String name) {
    
    
		//将给定类名的'.'覆盖成'/'后,后面拼接上'.class',以形成类路径
		String internalName = name.replace('.', '/') + CLASS_FILE_SUFFIX;
		//通过父ClassLoader的getResourceAsStream方法加载标准类文件。
		return getParent().getResourceAsStream(internalName);
	}


	/**
	 * Transformation hook to be implemented by subclasses.
	 * <p>转换将由子类实现,钩子方法</p>
	 * <p>The default implementation simply returns the given bytes as-is.
	 * <p>默认实现只是按原样返回给定的字节</p>
	 * @param name the fully-qualified name of the class being transformed
	 *             -- 要转换的类的全限定名称
	 * @param bytes the raw bytes of the class
	 *              -- 类的原始字节
	 * @return the transformed bytes (never {@code null};
	 * same as the input bytes if the transformation produced no changes)
	 * -- 转换后的字节(从不为{@code null};如果转换没有变化,则与传入的字节相同)
	 */
	protected byte[] transformIfNecessary(String name, byte[] bytes) {
    
    
		return bytes;
	}

}

SmartClassLoader

/**
 * Interface to be implemented by a reloading-aware ClassLoader
 * (e.g. a Groovy-based ClassLoader). Detected for example by
 * Spring's CGLIB proxy factory for making a caching decision.
 * <p>要由可重新加载的ClassLoader(例如,基于Groovy的ClassLoader)
 * 实现的接口。例如,由Spring的CGLIB代理工厂检测到是否做出了缓存
 * 决定
 * </p>
 *
 * <p>If a ClassLoader does <i>not</i> implement this interface,
 * then all of the classes obtained from it should be considered
 * as not reloadable (i.e. cacheable).
 * <p>如果ClassLoader没有实现该接口,则从该接口获得的所有类都应
 * 被视为无法重载(即可缓存)</p>
 * @author Juergen Hoeller
 * @since 2.5.1
 */
public interface SmartClassLoader {
    
    

	/**
	 * Determine whether the given class is reloadable (in this ClassLoader).
	 * <p>确定给定的类是否可重载(在此ClassLoader中)</p>
	 * <p>Typically used to check whether the result may be cached (for this
	 * ClassLoader) or whether it should be reobtained every time.
	 * <p>通常用于检查结果是否可以缓存(针对此ClassLoader)或是应重新获取</p>
	 * @param clazz the class to check (usually loaded from this ClassLoader)
	 *              - 要检查的类(通常从此ClassLoaser加载)
	 * @return whether the class should be expected to appear in a reloaded
	 * version (with a different {@code Class} object) later on
	 * - 以后是否应该期望该类出现在重新加载的版本中(具有不同的Class对象)
	 */
	boolean isClassReloadable(Class<?> clazz);

}

DecoratingClassLoader

/**
 * Base class for decorating ClassLoaders such as {@link OverridingClassLoader}
 * and {@link org.springframework.instrument.classloading.ShadowingClassLoader},
 * providing common handling of excluded packages and classes.
 * <p>装饰ClassLoader的基类,例如{@link OverridingClassLoader} 和
 * {@link org.springframework.instrument.classloading.ShadowingClassLoader},
 * 提供对排除的包和类的通用处理。</p>
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @since 2.5.2
 */
public abstract class DecoratingClassLoader extends ClassLoader {
    
    

	static {
    
    
		//https://www.jianshu.com/p/8210e891f564,
		// 通过该方法,可以使得ClassLoader执行并行加载机制,提高加载效率。
		ClassLoader.registerAsParallelCapable();
	}

	/**
	 * 要排除的包
	 */
	private final Set<String> excludedPackages = Collections.newSetFromMap(new ConcurrentHashMap<>(8));

	/**
	 * 要排除的类
	 */
	private final Set<String> excludedClasses = Collections.newSetFromMap(new ConcurrentHashMap<>(8));


	/**
	 * Create a new DecoratingClassLoader with no parent ClassLoader.
	 */
	public DecoratingClassLoader() {
    
    
	}

	/**
	 * Create a new DecoratingClassLoader using the given parent ClassLoader
	 * for delegation.
	 */
	public DecoratingClassLoader(@Nullable ClassLoader parent) {
    
    
		super(parent);
	}


	/**
	 * Add a package name to exclude from decoration (e.g. overriding).
	 * <p>Any class whose fully-qualified name starts with the name registered
	 * here will be handled by the parent ClassLoader in the usual fashion.
	 * @param packageName the package name to exclude
	 */
	public void excludePackage(String packageName) {
    
    
		Assert.notNull(packageName, "Package name must not be null");
		this.excludedPackages.add(packageName);
	}

	/**
	 * Add a class name to exclude from decoration (e.g. overriding).
	 * <p>添加要从装饰中排除的类名(例如,覆盖)。</p>
	 * <p>Any class name registered here will be handled by the parent
	 * ClassLoader in the usual fashion.
	 * <p>此处注册的任何类名称都将由父ClassLoader以常规方式处理。.</p>
	 * @param className the class name to exclude
	 */
	public void excludeClass(String className) {
    
    
		Assert.notNull(className, "Class name must not be null");
		this.excludedClasses.add(className);
	}

	/**
	 * Determine whether the specified class is excluded from decoration
	 * by this class loader.
	 * <p>确定此类加载器是否将指定的类从装饰中排除。</p>
	 * <p>The default implementation checks against excluded packages and classes.
	 * <p>默认实现检查排除的包和类</p>
	 * @param className the class name to check
	 * @return whether the specified class is eligible
	 * @see #excludePackage
	 * @see #excludeClass
	 */
	protected boolean isExcluded(String className) {
    
    
		if (this.excludedClasses.contains(className)) {
    
    
			return true;
		}
		for (String packageName : this.excludedPackages) {
    
    
			if (className.startsWith(packageName)) {
    
    
				return true;
			}
		}
		return false;
	}

}

猜你喜欢

转载自blog.csdn.net/qq_30321211/article/details/108324434