一、前言
关于spring-context包中定义org.springframework.instrument.classloading.LoadTimeWeaver类加载器运行接口、org.springframework.instrument.classloading.websphere.WebSphereLoadTimeWeaver对于websphere类加载器实现类,通过该源码示例有足于熟悉了解websphere加载器入口及自定义websphere类加载器等。
二、源码示例
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.WebSphereLoadTimeWeaver实现类
package org.springframework.instrument.classloading.websphere;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import org.springframework.core.OverridingClassLoader;@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 @b@ new OverridingClassLoader(this.classLoader.getClassLoader(), this.classLoader@b@ .getThrowawayClassLoader());@b@ }@b@}
package org.springframework.instrument.classloading.websphere;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import java.lang.reflect.Constructor;@b@import java.lang.reflect.Field;@b@import java.lang.reflect.InvocationHandler;@b@import java.lang.reflect.InvocationTargetException;@b@import java.lang.reflect.Method;@b@import java.lang.reflect.Proxy;@b@import java.util.List;@b@import org.springframework.util.Assert;@b@@b@class WebSphereClassLoaderAdapter@b@{@b@ private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader";@b@ private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin";@b@ private static final String PLUGINS_FIELD = "preDefinePlugins";@b@ private ClassLoader classLoader;@b@ private Class<?> wsPreProcessorClass;@b@ private Method addPreDefinePlugin;@b@ private Constructor<? extends ClassLoader> cloneConstructor;@b@ private Field transformerList;@b@@b@ public WebSphereClassLoaderAdapter(ClassLoader classLoader)@b@ {@b@ try@b@ {@b@ wsCompoundClassLoaderClass = classLoader.loadClass("com.ibm.ws.classloader.CompoundClassLoader");@b@ this.cloneConstructor = classLoader.getClass().getDeclaredConstructor(new Class[] { wsCompoundClassLoaderClass });@b@ this.cloneConstructor.setAccessible(true);@b@@b@ this.wsPreProcessorClass = classLoader.loadClass("com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin");@b@ this.addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", new Class[] { this.wsPreProcessorClass });@b@ this.transformerList = wsCompoundClassLoaderClass.getDeclaredField("preDefinePlugins");@b@ this.transformerList.setAccessible(true);@b@ }@b@ catch (Throwable ex) {@b@ throw new IllegalStateException("Could not initialize WebSphere LoadTimeWeaver because WebSphere API classes are not available", ex);@b@ }@b@@b@ if (!(wsCompoundClassLoaderClass.isInstance(classLoader)))@b@ throw new IllegalArgumentException("ClassLoader must be instance of com.ibm.ws.classloader.CompoundClassLoader");@b@@b@ this.classLoader = classLoader;@b@ }@b@@b@ public ClassLoader getClassLoader()@b@ {@b@ return this.classLoader;@b@ }@b@@b@ public void addTransformer(ClassFileTransformer transformer) {@b@ Assert.notNull(transformer, "ClassFileTransformer must not be null");@b@ try {@b@ InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);@b@ Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(), new Class[] { this.wsPreProcessorClass }, adapter);@b@@b@ this.addPreDefinePlugin.invoke(this.classLoader, new Object[] { adapterInstance });@b@ }@b@ catch (InvocationTargetException ex) {@b@ throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());@b@ }@b@ catch (Throwable ex) {@b@ throw new IllegalStateException("Could not invoke WebSphere addPreDefinePlugin method", ex);@b@ }@b@ }@b@@b@ public ClassLoader getThrowawayClassLoader() {@b@ try {@b@ ClassLoader loader = (ClassLoader)this.cloneConstructor.newInstance(new Object[] { getClassLoader() });@b@@b@ List list = (List)this.transformerList.get(loader);@b@ list.clear();@b@ return loader;@b@ }@b@ catch (InvocationTargetException ex) {@b@ throw new IllegalStateException("WebSphere CompoundClassLoader constructor failed", ex.getCause());@b@ }@b@ catch (Throwable ex) {@b@ throw new IllegalStateException("Could not construct WebSphere CompoundClassLoader", ex);@b@ }@b@ }@b@}
package org.springframework.instrument.classloading.websphere;@b@@b@import java.lang.instrument.ClassFileTransformer;@b@import java.lang.reflect.InvocationHandler;@b@import java.lang.reflect.Method;@b@import java.security.CodeSource;@b@import org.springframework.util.FileCopyUtils;@b@@b@class WebSphereClassPreDefinePlugin@b@ implements InvocationHandler@b@{@b@ private final ClassFileTransformer transformer;@b@@b@ public WebSphereClassPreDefinePlugin(ClassFileTransformer transformer)@b@ {@b@ this.transformer = transformer;@b@ ClassLoader classLoader = transformer.getClass().getClassLoader();@b@ try@b@ {@b@ String dummyClass = Dummy.class.getName().replace('.', '/');@b@ byte[] bytes = FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream(dummyClass + ".class"));@b@ transformer.transform(classLoader, dummyClass, null, null, bytes);@b@ }@b@ catch (Throwable ex) {@b@ throw new IllegalArgumentException("Cannot load transformer", ex);@b@ }@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 ("transformClass".equals(name)) {@b@ return transform((String)args[0], (byte[])(byte[])args[1], (CodeSource)args[2], (ClassLoader)args[3]);@b@ }@b@@b@ throw new IllegalArgumentException("Unknown method: " + method);@b@ }@b@@b@ protected byte[] transform(String className, byte[] classfileBuffer, CodeSource codeSource, ClassLoader classLoader)@b@ throws Exception@b@ {@b@ byte[] result = this.transformer.transform(classLoader, className.replace('.', '/'), null, null, classfileBuffer);@b@ return ((result != null) ? result : classfileBuffer);@b@ }@b@@b@ public String toString()@b@ {@b@ return super.getClass().getName() + " for transformer: " + this.transformer;@b@ }@b@@b@ private static class Dummy@b@ {@b@ }@b@}