//代码生成、编译、重新动态loader到JVM中
public class YustClassLoader extends ClassLoader{
private File baseDir;
public YustClassLoader() {
String baseDir = YustClassLoader.class.getResource("").getPath();
this.baseDir = new File(baseDir) ;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = YustClassLoader.class.getPackage().getName();
if(Objects.nonNull(baseDir)){
File classFile = new File(baseDir, name.replaceAll("\\.", "/") + ".class");
if (classFile.exists()){
try(FileInputStream in =new FileInputStream(classFile); ByteArrayOutputStream 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 (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
classFile.delete();
}
}
}
return null;
}
}
public interface YustInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
public class YustMeipo implements YustInvocationHandler {
private Person target;//被代理对象的引用作为一个成员变量进行保存下来了
public Object getInstance(Person target)throws Exception{
this.target=target;
Class clazz = target.getClass();
System.out.println("被代理对象的class是:"+clazz);
return YustProxy.newProxyInstance(new YustClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是媒婆:你的性别是:"+this.target.getSex()+"得给你找个异性");
System.out.println("-----------------------------");
method.invoke(this.target, args);
System.out.println("-----------------------------");
return null;
}
}
public class YustProxy {
private static String ln = "\r\n";
public static Object newProxyInstance(YustClassLoader classLoader,Class<?>[] interfaces,YustInvocationHandler h){
try{
//1、生成源代码
String proxySrc = generateSrc(interfaces[0]);
//2、将生成的源代码输出到磁盘,保存为.java文件
String filePath = YustProxy.class.getResource("").getPath();
File f = new File(filePath + "$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 = classLoader.findClass("$Proxy0");
Constructor c = proxyClass.getConstructor(YustInvocationHandler.class);
f.delete();
//5.返回被代理后的代理对象
return c.newInstance(h);
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class<?> interfaces){
StringBuffer src = new StringBuffer();
src.append("package com.yust5273.proxy.custom;" + ln);
src.append("import java.lang.reflect.Method;" + ln);
src.append("import com.yust5273.proxy.custom.YustInvocationHandler" + ln);
src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln);
src.append("YustInvocationHandler h;" + ln);
src.append("public $Proxy0(YustInvocationHandler 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();
}
}
public class YustTestFindLove {
public static void main(String[] args){
try {
Person obj =(Person) new YustMeipo().getInstance(new XiaoXingXing());
System.out.println(obj.getClass());
obj.findLove();
//代理对象的实现原理
//1.拿到被代理对象的引用,然后获取它的接口、
//2.JDK代理 就会重新生成一个类同时实现我们给的代理对象的所实现的接口
//3.把被代理对象的引用也拿到了
//4.重新生成一个class字节码
//5.然后编译
} catch (Exception e) {
e.printStackTrace();
}
}
}
网友评论