简介
最近在学习 Java 中类加载器的时候,突发奇想。本篇文章主要记录,反射的使用方法,以及使用动态代理往 Java 程序中注入代码。
编写 Java 程序
1、新建一个包com.qianyu.controller
,在该包下新建一个类Executor
,用于模拟程序的主要逻辑。
package com.qianyu.controller;
import java.util.Random;
public class Executor {
public String run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new Random().nextLong() + "";
}
}
上面的程序很简单,暂停一秒之后,返回一个随机字符串
2、新建com.qianyu.App
类,增加一个静态属性executor
,编写主函数循环调用 run 方法
package com.qianyu;
import com.qianyu.controller.Executor;
public class App {
private static Executor executor = new Executor();
public static void main(String[] args) {
while(true){
String res = executor.run();
System.out.println("res = " + res);
}
}
}
3、先编译代码,然后打包为 app.jar
javac com/qianyu/App.java -d .
jar -cvf app.jar -C . .
4、然后我们就可以运行 app.jar 程序
java -cp app.jar com.qianyu.App
运行结果:
通过反射注入代码
1、新建 maven 项目,引入 cglib 依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
2、首先,使用类加载器,加载 app.jar 文件
String path = "file:E:\\User\\Desktop\\代码注入测试\\app.jar";
URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL(path)});
3、获取 Executor 类,使用动态代理创建代理对象
Class<?> executorClazz = classLoader.loadClass("com.qianyu.controller.Executor");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(executorClazz);
enhancer.setCallback((MethodInterceptor) (object, method, args1, proxy) -> {
Object result = null;
try {
result = proxy.invokeSuper(object, args1);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("获取函数的返回值 : " + result);
System.out.println("自己的业务");
return result;
});
Object newExecutor = enhancer.create();
4、然后将 App 类里面的静态属性换成代理对象
Class<?> appClazz = classLoader.loadClass("com.qianyu.App");
Field executor = appClazz.getDeclaredField("executor");
executor.setAccessible(true);
executor.set(null, newExecutor);
5、通过反射执行 main 方法
Method method = appClazz.getDeclaredMethod("main", String[].class);
method.invoke(null, (Object) new String[1]);
运行结果:
全部代码
package pers.qianyu;
import net.sf.cglib.proxy.*;
import java.lang.reflect.*;
import java.net.*;
public class App {
public static void main(String[] args) throws Exception {
String path = "file:E:\\User\\Desktop\\代码注入测试\\app.jar";
URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL(path)});
Class<?> executorClazz = classLoader.loadClass("com.qianyu.controller.Executor");
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(executorClazz);
enhancer.setCallback((MethodInterceptor) (object, method, args1, proxy) -> {
Object result = null;
try {
result = proxy.invokeSuper(object, args1);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("获取函数的返回值 : " + result);
System.out.println("自己的业务");
return result;
});
Object newExecutor = enhancer.create();
Class<?> appClazz = classLoader.loadClass("com.qianyu.App");
Field executor = appClazz.getDeclaredField("executor");
executor.setAccessible(true);
executor.set(null, newExecutor);
Method method = appClazz.getDeclaredMethod("main", String[].class);
method.invoke(null, (Object) new String[1]);
}
}