一般來說,hook的應用場景就是修改或攔截某些系統類的方法及替換屬性
直接上代碼!
有一個接口IAction
public interface IAction {
void eat(String food);
}
People類中有一個"name"屬性,並實現了接口IAction
public class People implements IAction {
private String name = "小明";
@Override
public void eat(String food) {
System.out.println(name + "喫" + food);
}
}
動態代理類,實現InvocationHandler接口,構造函數傳入被代理的對象
public class DynamicProxyHandler implements InvocationHandler {
private Object proxied;// 被代理的對象
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 執行代理對象原來的方法之前,加入任何自己想要的動作
System.out.println(" ==== 代理方法接收的參數是:"+args[0]);
args[0] = "蘋果";
System.out.println(" ==== 改爲:"+args[0]);
// 執行代理對象原來的方法
return method.invoke(proxied,args);
}
}
public class Test {
public static void main(String[] args) {
System.out.println("-----正常操作-----");
normal();
System.out.println("\n-----hook代理-----");
hookInterface();
System.out.println("\n-----hook屬性-----");
hookAttr();
}
/**
* 正常操作
*/
public static void normal() {
People people = new People();
people.eat("梨子");
}
/**
* hook方法
*/
public static void hookInterface() {
People people = new People();
IAction iAction = (IAction) Proxy.newProxyInstance(
IAction.class.getClassLoader(),
new Class[]{IAction.class},
new DynamicProxyHandler(people));
iAction.eat("梨子"); // 雖然傳遞的是"梨子",但hook過程被修改了
}
/**
* hook屬性
*/
public static void hookAttr(){
try {
System.out.println(" ==== hook屬性,狸貓換太子,小明變小強");
People people = new People();
Field field = People.class.getDeclaredField("name");
field.setAccessible(true);
field.set(people, "小強");
people.eat("梨子");
} catch (Exception e) {
e.printStackTrace();
}
}
}
運行Test輸出:
-----正常操作-----
小明喫梨子
-----hook代理-----
==== 代理方法接收的參數是:梨子
==== 改爲:蘋果
小明喫蘋果
-----hook屬性-----
==== hook屬性,狸貓換太子,小明變小強
小強喫梨子