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;
}
}