USB接口类
package com.zemo.proxy;
/**
* USB接口类
*/
public interface USB {
/**
* 运行设备
*/
void open() throws Throwable;
void close();
}
鼠标USB接口实现类
package com.zemo.proxy;
/**
*鼠标
*/
public class MouseUSB implements USB {
@Override
public void open() {
System.out.println("连接鼠标USB接口");
}
@Override
public void close() {
System.out.println("关闭鼠标USB接口");
}
}
自定义InvocationHandler接口
package com.zemo.proxy;
import java.lang.reflect.Method;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
代理实现类
package com.zemo.proxy;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
private USB target;
// 获取被代理人的个人资料
public Object getInstance(USB target) throws Exception {
this.target = target;
Class clazz = target.getClass();
System.out.println("被代理对象的class是:" + clazz);
return Proxy.newProxyInstance(new ClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理开始");
System.out.println("-------------");
method.invoke(this.target, args);
System.out.println("-------------");
System.out.println("动态代理结束");
System.out.println();
return null;
}
}
生成代理对象类
package com.zemo.proxy;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* 生成代理对象$Proxy0.java和$Proxy0.jclass的代码
*/
public class Proxy {
private static String ln = "\r\n";
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
throws IllegalArgumentException {
try {
// 1.生成源代码
String proxySrc = generateSrc(interfaces[0]);
// 2.将生成的源代码输出到磁盘,保存.java文件
String path = java.net.URLDecoder.decode(Proxy.class.getResource("").getPath());
File f = new File(path + "$Proxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(proxySrc);
fw.flush();
fw.close();
// 3.编译源代码,并且生成.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(f);
CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close();
// 4.将class文件中的内容,动态加载到JVM中
Class<?> proxyClass = loader.findClass("$Proxy0");
Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class);
// f.delete(); //删除生成的Java文件
// 5.返回被代理后的代理对象
return constructor.newInstance(h);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 生成代码
*
* @param interfaces
* @return
*/
private static String generateSrc(Class<?> interfaces) {
StringBuffer src = new StringBuffer();
src.append("package com.zemo.proxy;" + ln);
src.append("import java.lang.reflect.Method;" + ln);
src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln);
src.append("InvocationHandler h;" + ln);
src.append("public $Proxy0(InvocationHandler h){" + ln);
src.append("this.h = h;" + ln);
src.append("}" + ln);
for (Method m : interfaces.getMethods()) {
src.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln);
src.append("try {" + ln);
src.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" + m.getName() + "\",new " +
"Class[]{});" + ln);
src.append("this.h.invoke(this,m,null);" + ln);
src.append("} catch(Throwable e){e.printStackTrace();}" + ln);
src.append("}" + ln);
}
src.append("}");
return src.toString();
}
;
}
Proxy.java会在编译路径下自动生成
$Proxy0.java
和$Proxy0.class
,注意$Proxy0.java
的包名和类名是在Proxy.java
中写死的
自定义ClassLoader类
package com.zemo.proxy;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 代码生成、编译、重新动态load到JVM中
*/
public class ClassLoader extends java.lang.ClassLoader {
private File baseDir;
public ClassLoader() {
String path = java.net.URLDecoder.decode(ClassLoader.class.getResource("").getPath());
this.baseDir = new File(path);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = ClassLoader.class.getPackage().getName() + "." + name;
if(baseDir != null) {
File classFile = new File(baseDir,name.replaceAll("\\.", "/")+".class");
if(classFile.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte [] buff = new byte[1024];
int len;
while((len = in.read(buff)) != -1) {
out.write(buff,0,len);
}
return defineClass(className,out.toByteArray(),0,out.size());
}catch (Exception e) {
e.printStackTrace();
}finally {
if(null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 删除class文件
classFile.delete();
}
}
}
return null;
}
}
测试类
package com.zemo.proxy;
/**
* @author Liam
* @version 1.0 2020/6/2
*/
public class Test {
public static void main(String[] args) throws Throwable {
USB obj = (USB) new ProxyHandler().getInstance(new MouseUSB());
System.out.println(obj.getClass());
obj.open();
obj.close();
}
}
测试结果
被代理对象的class是:class com.zemo.proxy.MouseUSB
class com.zemo.proxy.$Proxy0
动态代理开始
-------------
连接鼠标USB接口
-------------
动态代理结束
动态代理开始
-------------
关闭鼠标USB接口
-------------
动态代理结束