java – 添加代码到包私有库方法
|
我有一个包类私有方法的库类.通过子类直接覆盖此方法是不可选的.有没有办法,无论多么丑陋,执行自己的代码,当这个包私有方法从库内调用,例如使用AspectJ? 这是类的简化示例(packagePrivateMethod()实际上不是直接调用,而是从本机代码调用): public LibClass {
public LibClass() {
...
packagePrivateMethod();
...
}
void packagePrivateMethod() {
// <-- here I want to execute additional code
...
}
}
解决方法你可以使用相当重的方法.写一个小的Java代理SO post about that topic. 这样可以修改所有内容的字节码,但是在执行前需要修改该字节码. 当然,您也可以通过修改类文件来静态地执行此操作,将现有的字节代码替换为您在上述步骤3中创建的字节码. 如果您不想/不能静态替换类的字节码,则必须在运行时对字节码进行修改.对于使用Java代理是一个很好而坚实的想法. 由于这是所有的抽象直到现在,我添加了一个例子,它将拦截你的库类的加载,在一个包私有方法中注入一个方法调用.当main方法执行时,可以从输出中看到注入的方法直接在库类的代码之前调用.如果你添加return;作为注入代码,您还可以完全阻止该方法的执行. 所以这里是使用Java 6和JavaAssist解决的问题的一个例子的代码.如果你想沿着这条路径走,并使用像Java 7这样的新东西,那么你只需要用ASM替换字节码操作.这有点不太可读,但也不完全是火箭科学. 主要类: package com.aop.example;
public class Main {
public static void main(String[] args) {
System.out.println("Main starts!");
LibClass libClass = new LibClass();
System.out.println("Main finished!");
}
}
你的LibClass: package com.aop.example;
public class LibClass {
public LibClass() {
packagePrivateMethod();
}
void packagePrivateMethod() {
// <-- here I want to execute additional code
System.out.println("In packagePrivateMethod");
}
}
中介: package com.aop.agent;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.LoaderClassPath;
import javassist.NotFoundException;
public class Agent {
public static void premain(String agentArgs,Instrumentation instr) {
System.out.println("Agent starts!");
instr.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader classLoader,String className,Class<?> arg2,ProtectionDomain arg3,byte[] bytes)
throws IllegalClassFormatException {
System.out.println("Before loading class " + className);
final String TARGET_CLASS = "com/aop/example/LibClass";
if (!className.equals(TARGET_CLASS)) {
return null;
}
LoaderClassPath path = new LoaderClassPath(classLoader);
ClassPool pool = new ClassPool();
pool.appendSystemPath();
pool.appendClassPath(path);
try {
CtClass targetClass = pool.get(TARGET_CLASS.replace('/','.'));
System.out.println("Enhancing class " + targetClass.getName());
CtMethod[] methods = targetClass.getDeclaredMethods();
for (CtMethod method : methods) {
if (!method.getName().contains("packagePrivateMethod")) {
continue;
}
System.out.println("Enhancing method " + method.getSignature());
String myMethodInvocation = "com.aop.agent.Agent.myMethodInvocation();";
method.insertBefore(myMethodInvocation);
}
System.out.println("Enhanced bytecode");
return targetClass.toBytecode();
}
catch (CannotCompileException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
catch (NotFoundException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
});
}
public static void myMethodInvocation() {
System.out.println("<<<My injected code>>>!");
}
}
运行示例的命令(您必须将代理放在具有属性Premain-Class的清单的jar中:com.aop.agent.Agent: %JAVA_HOME%binjava -cp .;..javassist-3.12.1.GA.jar -javaagent:....agent.jar com.aop.example.Main 该示例的输出运行如下命令: Agent starts! Before loading class com/aop/example/Main Main starts! Before loading class com/aop/example/LibClass Enhancing class com.aop.example.LibClass Enhancing method ()V Enhanced bytecode <<<My injected code>>>! In packagePrivateMethod Main finished! Before loading class java/lang/Shutdown Before loading class java/lang/Shutdown$Lock (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
