如果您的运行时环境允许使用自定义类加载器,您应该能够将第三方类 A 替换为使用反射调用原始类 A 的自定义委托类。
这是委托类 A 的示例:
package fi.test;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ClassA {
private static final Class<?> clazz;
private static final Method doSomething;
private Object instance;
static {
ClassLoader classLoader = new ClassLoader(ClassA.class.getClassLoader()) {
@Override
public synchronized Class<?> loadClass(String name)
throws ClassNotFoundException {
if (!name.equals(ClassA.class.getName())) {
return super.loadClass(name);
}
Class<?> clazz = findLoadedClass(name);
if (clazz == null) {
// The original class A is stored as ClassA.class.orig
InputStream inputStream = getParent().getResourceAsStream(
"fi/test/ClassA.class.orig");
try {
byte[] buffer = new byte[100000];
int length = inputStream.read(buffer);
clazz = defineClass(name, buffer, 0, length);
} catch (IOException exception) {
throw new ClassNotFoundException("", exception);
} finally {
try {
inputStream.close();
} catch (IOException exception) {
}
}
}
return clazz;
}
};
try {
// Class A
clazz = classLoader.loadClass(ClassA.class.getName());
// Do something
doSomething = clazz.getMethod("doSomething", new Class<?>[0]);
} catch (Exception exception) {
throw new Error(exception);
}
}
public ClassA() {
try {
instance = clazz.newInstance();
} catch (InstantiationException exception) {
throw new RuntimeException(exception);
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
}
}
public void doSomething() {
try {
doSomething.invoke(instance, new Object[0]);
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
}
}
}
这是原来的 A 类:
package fi.test;
public class ClassA {
public void doSomething() {
System.out.println("This is magic!");
}
}
这是我用来测试委托的类:
package fi.test;
public class Tester {
public static void main(String[] args) {
ClassA instance = new ClassA();
instance.doSomething();
}
}