一、前言
基于spring-context(4.1.4)定义的org.springframework.instrument.classloading.LoadTimeWeaver服务类加载器接口,分配针对glassfish、jboss、tomcat、weblogic、websphere应用服务容器对于的类加载器ClassLoader实现各自的差异性部分(GlassFishLoadTimeWeaver、JBossLoadTimeWeaver、TomcatLoadTimeWeaver、WebLogicLoadTimeWeaver、WebSphereLoadTimeWeaver)。
二、源码说明
1.LoadTimeWeaver接口
package org.springframework.instrument.classloading;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@@b@public abstract interface LoadTimeWeaver@b@{@b@ public abstract void addTransformer(ClassFileTransformer paramClassFileTransformer);@b@@b@ public abstract ClassLoader getInstrumentableClassLoader();@b@@b@ public abstract ClassLoader getThrowawayClassLoader();@b@}
2.GlassFishLoadTimeWeaver实现类
package org.springframework.instrument.classloading.glassfish;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Method;@b@import org.springframework.instrument.classloading.LoadTimeWeaver;@b@import org.springframework.util.Assert;@b@import org.springframework.util.ClassUtils;@b@@b@public class GlassFishLoadTimeWeaver@b@ implements LoadTimeWeaver@b@{@b@ private static final String INSTRUMENTABLE_LOADER_CLASS_NAME = "org.glassfish.api.deployment.InstrumentableClassLoader";@b@ private final ClassLoader classLoader;@b@ private final Method addTransformerMethod;@b@ private final Method copyMethod;@b@@b@ public GlassFishLoadTimeWeaver()@b@ {@b@ this(ClassUtils.getDefaultClassLoader());@b@ }@b@@b@ public GlassFishLoadTimeWeaver(ClassLoader classLoader) {@b@ Assert.notNull(classLoader, "ClassLoader must not be null");@b@ try@b@ {@b@ instrumentableLoaderClass = classLoader.loadClass("org.glassfish.api.deployment.InstrumentableClassLoader");@b@ }@b@ catch (ClassNotFoundException ex) {@b@ throw new IllegalStateException("Could not initialize GlassFishLoadTimeWeaver because GlassFish API classes are not available", ex);@b@ }@b@ try@b@ {@b@ this.addTransformerMethod = instrumentableLoaderClass.getMethod("addTransformer", new Class[] { ClassFileTransformer.class });@b@ this.copyMethod = instrumentableLoaderClass.getMethod("copy", new Class[0]);@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not initialize GlassFishLoadTimeWeaver because GlassFish API classes are not available", ex);@b@ }@b@@b@ ClassLoader clazzLoader = null;@b@@b@ for (ClassLoader cl = classLoader; (cl != null) && (clazzLoader == null); cl = cl.getParent()) {@b@ if (instrumentableLoaderClass.isInstance(cl))@b@ clazzLoader = cl;@b@@b@ }@b@@b@ if (clazzLoader == null)@b@ {@b@ throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: A [" + instrumentableLoaderClass@b@ .getName() + "] implementation is required.");@b@ }@b@@b@ this.classLoader = clazzLoader;@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer)@b@ {@b@ try@b@ {@b@ this.addTransformerMethod.invoke(this.classLoader, new Object[] { transformer });@b@ }@b@ catch (InvocationTargetException ex) {@b@ throw new IllegalStateException("GlassFish addTransformer method threw exception", ex.getCause());@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not invoke GlassFish addTransformer method", ex);@b@ }@b@ }@b@@b@ public ClassLoader getInstrumentableClassLoader()@b@ {@b@ return this.classLoader;@b@ }@b@@b@ public ClassLoader getThrowawayClassLoader()@b@ {@b@ try {@b@ return ((ClassLoader)this.copyMethod.invoke(this.classLoader, new Object[0]));@b@ }@b@ catch (InvocationTargetException ex) {@b@ throw new IllegalStateException("GlassFish copy method threw exception", ex.getCause());@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not invoke GlassFish copy method", ex);@b@ }@b@ }@b@}
3.JBossLoadTimeWeaver
package org.springframework.instrument.classloading.jboss;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import org.springframework.instrument.classloading.LoadTimeWeaver;@b@import org.springframework.instrument.classloading.SimpleThrowawayClassLoader;@b@import org.springframework.util.Assert;@b@import org.springframework.util.ClassUtils;@b@@b@public class JBossLoadTimeWeaver@b@ implements LoadTimeWeaver@b@{@b@ private final JBossClassLoaderAdapter adapter;@b@@b@ public JBossLoadTimeWeaver()@b@ {@b@ this(ClassUtils.getDefaultClassLoader());@b@ }@b@@b@ public JBossLoadTimeWeaver(ClassLoader classLoader)@b@ {@b@ Assert.notNull(classLoader, "ClassLoader must not be null");@b@ if (classLoader.getClass().getName().startsWith("org.jboss.modules"))@b@ {@b@ this.adapter = new JBossModulesAdapter(classLoader);@b@ }@b@ else@b@ {@b@ this.adapter = new JBossMCAdapter(classLoader);@b@ }@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer)@b@ {@b@ this.adapter.addTransformer(transformer);@b@ }@b@@b@ public ClassLoader getInstrumentableClassLoader()@b@ {@b@ return this.adapter.getInstrumentableClassLoader();@b@ }@b@@b@ public ClassLoader getThrowawayClassLoader()@b@ {@b@ return new SimpleThrowawayClassLoader(getInstrumentableClassLoader());@b@ }@b@}
package org.springframework.instrument.classloading.jboss;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.Method;@b@import org.springframework.util.ReflectionUtils;@b@@b@class JBossModulesAdapter@b@ implements JBossClassLoaderAdapter@b@{@b@ private static final String DELEGATING_TRANSFORMER_CLASS_NAME = "org.jboss.as.server.deployment.module.DelegatingClassFileTransformer";@b@ private final ClassLoader classLoader;@b@ private final Method addTransformer;@b@ private final Object delegatingTransformer;@b@@b@ public JBossModulesAdapter(ClassLoader loader)@b@ {@b@ this.classLoader = loader;@b@ try {@b@ Field transformer = ReflectionUtils.findField(loader.getClass(), "transformer");@b@ transformer.setAccessible(true);@b@ this.delegatingTransformer = transformer.get(loader);@b@ if (!(this.delegatingTransformer.getClass().getName().equals("org.jboss.as.server.deployment.module.DelegatingClassFileTransformer")))@b@ {@b@ throw new IllegalStateException("Transformer not of the expected type DelegatingClassFileTransformer: " + this.delegatingTransformer@b@ .getClass().getName());@b@ }@b@ this.addTransformer = ReflectionUtils.findMethod(this.delegatingTransformer.getClass(), "addTransformer", new Class[] { ClassFileTransformer.class });@b@@b@ this.addTransformer.setAccessible(true);@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not initialize JBoss 7 LoadTimeWeaver", ex);@b@ }@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer)@b@ {@b@ try {@b@ this.addTransformer.invoke(this.delegatingTransformer, new Object[] { transformer });@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not add transformer on JBoss 7 ClassLoader " + this.classLoader, ex);@b@ }@b@ }@b@@b@ public ClassLoader getInstrumentableClassLoader()@b@ {@b@ return this.classLoader;@b@ }@b@}
package org.springframework.instrument.classloading.jboss;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import java.lang.reflect.InvocationHandler;@b@import java.lang.reflect.Method;@b@import java.security.ProtectionDomain;@b@@b@class JBossMCTranslatorAdapter@b@ implements InvocationHandler@b@{@b@ private final ClassFileTransformer transformer;@b@@b@ public JBossMCTranslatorAdapter(ClassFileTransformer transformer)@b@ {@b@ this.transformer = transformer;@b@ }@b@@b@ public Object invoke(Object proxy, Method method, Object[] args)@b@ throws Throwable@b@ {@b@ String name = method.getName();@b@ if ("equals".equals(name))@b@ return Boolean.valueOf(proxy == args[0]);@b@@b@ if ("hashCode".equals(name))@b@ return Integer.valueOf(super.hashCode());@b@@b@ if ("toString".equals(name))@b@ return toString();@b@@b@ if ("transform".equals(name)) {@b@ return transform((ClassLoader)args[0], (String)args[1], (Class)args[2], (ProtectionDomain)args[3], (byte[])(byte[])args[4]);@b@ }@b@@b@ if ("unregisterClassLoader".equals(name)) {@b@ unregisterClassLoader((ClassLoader)args[0]);@b@ return null;@b@ }@b@@b@ throw new IllegalArgumentException("Unknown method: " + method);@b@ }@b@@b@ public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)@b@ throws Exception@b@ {@b@ return this.transformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);@b@ }@b@@b@ public void unregisterClassLoader(ClassLoader loader)@b@ {@b@ }@b@@b@ public String toString()@b@ {@b@ StringBuilder builder = new StringBuilder(super.getClass().getName());@b@ builder.append(" for transformer: ");@b@ builder.append(this.transformer);@b@ return builder.toString();@b@ }@b@}
4.TomcatLoadTimeWeaver
package org.springframework.instrument.classloading.tomcat;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Method;@b@import org.springframework.instrument.classloading.LoadTimeWeaver;@b@import org.springframework.util.Assert;@b@import org.springframework.util.ClassUtils;@b@@b@public class TomcatLoadTimeWeaver@b@ implements LoadTimeWeaver@b@{@b@ private static final String INSTRUMENTABLE_LOADER_CLASS_NAME = "org.apache.tomcat.InstrumentableClassLoader";@b@ private final ClassLoader classLoader;@b@ private final Method addTransformerMethod;@b@ private final Method copyMethod;@b@@b@ public TomcatLoadTimeWeaver()@b@ {@b@ this(ClassUtils.getDefaultClassLoader());@b@ }@b@@b@ public TomcatLoadTimeWeaver(ClassLoader classLoader) {@b@ Assert.notNull(classLoader, "ClassLoader must not be null");@b@ this.classLoader = classLoader;@b@ try@b@ {@b@ instrumentableLoaderClass = classLoader.loadClass("org.apache.tomcat.InstrumentableClassLoader");@b@ if (!(instrumentableLoaderClass.isInstance(classLoader)))@b@ {@b@ instrumentableLoaderClass = classLoader.getClass();@b@ }@b@ }@b@ catch (ClassNotFoundException ex)@b@ {@b@ instrumentableLoaderClass = classLoader.getClass();@b@ }@b@ try@b@ {@b@ this.addTransformerMethod = instrumentableLoaderClass.getMethod("addTransformer", new Class[] { ClassFileTransformer.class });@b@@b@ Method copyMethod = ClassUtils.getMethodIfAvailable(instrumentableLoaderClass, "copyWithoutTransformers", new Class[0]);@b@ if (copyMethod == null)@b@ {@b@ copyMethod = instrumentableLoaderClass.getMethod("getThrowawayClassLoader", new Class[0]);@b@ }@b@ this.copyMethod = copyMethod;@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not initialize TomcatLoadTimeWeaver because Tomcat API classes are not available", ex);@b@ }@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer)@b@ {@b@ try@b@ {@b@ this.addTransformerMethod.invoke(this.classLoader, new Object[] { transformer });@b@ }@b@ catch (InvocationTargetException ex) {@b@ throw new IllegalStateException("Tomcat addTransformer method threw exception", ex.getCause());@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not invoke Tomcat addTransformer method", ex);@b@ }@b@ }@b@@b@ public ClassLoader getInstrumentableClassLoader()@b@ {@b@ return this.classLoader;@b@ }@b@@b@ public ClassLoader getThrowawayClassLoader()@b@ {@b@ try {@b@ return ((ClassLoader)this.copyMethod.invoke(this.classLoader, new Object[0]));@b@ }@b@ catch (InvocationTargetException ex) {@b@ throw new IllegalStateException("Tomcat copy method threw exception", ex.getCause());@b@ }@b@ catch (Exception ex) {@b@ throw new IllegalStateException("Could not invoke Tomcat copy method", ex);@b@ }@b@ }@b@}
5.WebLogicLoadTimeWeaver
package org.springframework.instrument.classloading.weblogic;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import org.springframework.instrument.classloading.LoadTimeWeaver;@b@import org.springframework.util.Assert;@b@import org.springframework.util.ClassUtils;@b@@b@public class WebLogicLoadTimeWeaver@b@ implements LoadTimeWeaver@b@{@b@ private final WebLogicClassLoaderAdapter classLoader;@b@@b@ public WebLogicLoadTimeWeaver()@b@ {@b@ this(ClassUtils.getDefaultClassLoader());@b@ }@b@@b@ public WebLogicLoadTimeWeaver(ClassLoader classLoader)@b@ {@b@ Assert.notNull(classLoader, "ClassLoader must not be null");@b@ this.classLoader = new WebLogicClassLoaderAdapter(classLoader);@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer)@b@ {@b@ this.classLoader.addTransformer(transformer);@b@ }@b@@b@ public ClassLoader getInstrumentableClassLoader()@b@ {@b@ return this.classLoader.getClassLoader();@b@ }@b@@b@ public ClassLoader getThrowawayClassLoader()@b@ {@b@ return this.classLoader.getThrowawayClassLoader();@b@ }@b@}
6.WebSphereLoadTimeWeaver
package org.springframework.instrument.classloading.websphere;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import org.springframework.instrument.classloading.LoadTimeWeaver;@b@import org.springframework.util.Assert;@b@import org.springframework.util.ClassUtils;@b@@b@public class WebSphereLoadTimeWeaver@b@ implements LoadTimeWeaver@b@{@b@ private final WebSphereClassLoaderAdapter classLoader;@b@@b@ public WebSphereLoadTimeWeaver()@b@ {@b@ this(ClassUtils.getDefaultClassLoader());@b@ }@b@@b@ public WebSphereLoadTimeWeaver(ClassLoader classLoader)@b@ {@b@ Assert.notNull(classLoader, "ClassLoader must not be null");@b@ this.classLoader = new WebSphereClassLoaderAdapter(classLoader);@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer)@b@ {@b@ this.classLoader.addTransformer(transformer);@b@ }@b@@b@ public ClassLoader getInstrumentableClassLoader()@b@ {@b@ return this.classLoader.getClassLoader();@b@ }@b@@b@ public ClassLoader getThrowawayClassLoader()@b@ {@b@ return this.classLoader.getThrowawayClassLoader();@b@ }@b@}