欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java自定义动态代理

程序员文章站 2024-03-22 16:06:16
...

java自定义动态代理,代码创建->编译->载入

注:如ToolProvider.getSystemJavaCompiler() 返回 null则需JAVA_HOME由java\jdk改为Java\jre,同时将jdk\lib下将tools.jar复制到jre\lib下,改了JAVA_HOME后记得把path还是改成原来的,因为JAVA_HOME变了

HRProxySourceCreator.java

Test.java 测试类

package herui.core;

import java.lang.reflect.Method;

import herui.entity.A;
import herui.entity.B;
import herui.entity.C;

public class Test {

	public static void main(String[] args) {
		
		HRProxy hrProxy = HRProxy.newProxyInstance(B.class.getInterfaces(), new HRInvocationHandler() {
			
			@Override
			public Object invoke(Object proxyObj, Method method, Object[] args) {
				System.out.println("调用:"+method.getName());
				System.out.println("参数:");
				for(int i=0; i< args.length;++i) {
					System.out.print(args[i]+",");
				}
				try {
					System.out.println("\n返回结果:");
					return method.invoke(proxyObj, args);
				} catch (Exception e) {
					e.printStackTrace();
				}
				return null;
			}

		});
		
		B b = new B();
		A a = hrProxy.getProxyObject(A.class, b);
		System.out.println(a.add(3, 5));
		System.out.println(a.sub(13, 1));
		a.print("自定义动态代理");
		
		C c = new C();
		A a2 = hrProxy.getProxyObject(A.class, c);
		System.out.println(a2.add(3, 5));
		System.out.println(a2.sub(13, 1));
		a2.print("自定义动态代理");
	}

}

HRProxySourceCreator.java 代理类构建

package herui.core;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;

public class HRProxySourceCreator{

	final static String BR = "\r\n";
	final static String TB = "\t";
	final static String SP = " ";
	final static String CA = ",";
	final static String SN = ";";
	
	public static File create(Class<?>[] interfaces, HRInvocationHandler h) throws IOException {
		StringBuilder sBuilder = new StringBuilder();
		addPackage(sBuilder, interfaces);
		String className = addClassHead(sBuilder, interfaces);
		addClassBody(sBuilder, interfaces, className);
		System.out.println(sBuilder.toString());
		String path = HRProxySourceCreator.class.getResource("").getPath() + className+".java";
		File file = new File(path);
		FileOutputStream fos = new FileOutputStream(file);
		fos.write(sBuilder.toString().getBytes());
		fos.flush();
		fos.close();
		return file;
	}

	private static void addClassBody(StringBuilder sBuilder, Class<?>[] interfaces, String className) {
		sBuilder.append("{").append(BR)
		.append(TB).append("HRInvocationHandler h;").append(BR)
		.append(TB).append("Object tag;").append(BR)
		.append(TB).append("public ").append(className).append(" (").append("HRInvocationHandler h, Object tag) {").append(BR)
		.append(TB).append(TB).append("this.h = h;").append(BR)
		.append(TB).append(TB).append("this.tag = tag;").append(BR).append(TB).append("}");
		
		for(int i=0; i<interfaces.length; ++i) {
			Method[] methods = interfaces[i].getMethods();
			for(int j=0; j<methods.length; ++j) {
				addMethod(sBuilder, methods[j], interfaces[i].getName(), j);
			}
		}
		sBuilder.append(BR).append("}").append(BR);
	}

	private static void addMethod(StringBuilder sBuilder, Method method, String className, int index) {
		sBuilder.append(BR).append(BR).append(TB).append("public ").append(method.getReturnType().getName())
		.append(SP).append(method.getName()).append(SP)
		.append("(");
		Class<?>[] types = method.getParameterTypes();
		for (int i = 0; i < types.length; i++) {
			sBuilder.append(types[i].getTypeName()).append(SP).append("arg"+i).append(CA).append(SP);
		}
		sBuilder.delete(sBuilder.length()-2, sBuilder.length()-1);
		sBuilder.append(")").append(SP)
		.append("{").append(BR).append(TB).append(TB).append("Method method = ").append(className)
		.append(".class.getMethods()[").append(index).append("]").append(SN).append(BR);
		sBuilder.append(TB).append(TB).append("Object[] args = {");
		for (int i = 0; i < types.length; i++) {
			sBuilder.append("arg"+i).append(CA).append(SP);
		}
		sBuilder.delete(sBuilder.length()-2, sBuilder.length()-1)
		.append("}").append(SN).append(BR).append(TB).append(TB);
		if(!"void".equals(method.getReturnType().getName())) {
			sBuilder.append("return (").append(method.getReturnType().getName()).append(")");
		}
		sBuilder.append("h.invoke(tag, method, args)").append(SN).append(BR)
		.append(TB).append("}").append(BR);
	}

	private static String addClassHead(StringBuilder sBuilder, Class<?>[] interfaces) {
		sBuilder.append("public class ");
		String className = "$";
		for(int i=0; i<interfaces.length; ++i) {
			className += interfaces[i].getSimpleName();
		}
		sBuilder.append(className);
		
		sBuilder.append(" implements ");
		for(int i=0; i<interfaces.length; ++i) {
			sBuilder.append(interfaces[i].getName()).append(CA);
		}
		sBuilder.deleteCharAt(sBuilder.length()-1);
		sBuilder.append(SP);
		return className;
	}

	private static void addPackage(StringBuilder sBuilder, Class<?>[] interfaces) {
		sBuilder.append("package herui.core;").append(BR);
		sBuilder.append("import java.lang.reflect.Method;");
		sBuilder.append(BR).append(BR);
	}

}

HRProxy.java 代理类编译载入jvm,门面

package herui.core;

import java.io.File;
import java.lang.reflect.Constructor;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class HRProxy {
	private HRInvocationHandler h;
	private Class proxyClass;
	private HRProxy() {
		throw new RuntimeException("no new instance by the construtor");
	}
	private HRProxy(Class<?>[] interfaces, HRInvocationHandler h) {
		if(interfaces == null || h == null) {
			throw new RuntimeException("input invalid parameter");
		}
		this.h = h;
		try {
			File file = HRProxySourceCreator.create(interfaces, h);
			
			//把生成的.java文件编译成.class文件
			JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
			StandardJavaFileManager manage = compiler.getStandardFileManager(null, null, null);
			Iterable iterable = manage.getJavaFileObjects(file);

			JavaCompiler.CompilationTask task = compiler.getTask(null, manage, null, null, null, iterable);
			task.call();
			manage.close();
			// 编译生成的.class文件加载到JVM中来
			HRClassLoader loader = new HRClassLoader();
			proxyClass = loader.loadClass(file.getName().replace(".java", ""));
			file.delete();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public <T> T getProxyObject(Class<T> clzz, Object obj) {
		Constructor constructor = null;
		try {
			constructor = proxyClass.getConstructor(new Class[] {HRInvocationHandler.class, Object.class});
			return (T) constructor.newInstance(h, obj);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static HRProxy newProxyInstance(Class<?>[] interfaces, HRInvocationHandler h) {
		return new HRProxy(interfaces, h);
	}
}

HRClassLoader.java 自定义类加载器

package herui.core;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class HRClassLoader extends ClassLoader{

    private File classPathFile;

    public HRClassLoader(){
        String classPath = HRClassLoader.class.getResource("").getPath();
        this.classPathFile = new File(classPath);
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {

        String className = HRClassLoader.class.getPackage().getName() + "." + name;

        if(classPathFile != null){
            File classFile = new File(classPathFile, 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(out != null){
                        try {
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

        }

        return null;

    }
}

HRInvocationHandler.java 处理器接口

package herui.core;

import java.lang.reflect.Method;

public interface HRInvocationHandler {
	Object invoke(Object proxyObj, Method method, Object[] args);
}

A.java 接口

package herui.entity;

public interface A {
	Integer add(int a, int b);
	
	int sub(int a, int b);
	
	String print(String s);
}

B.java 实现类1

package herui.entity;

public class B implements A{

	@Override
	public Integer add(int a, int b) {
		return a+b;
	}

	@Override
	public int sub(int a, int b) {
		return a-b;
	}

	@Override
	public String print(String s) {
		if(s == null) {
			s = "";
		}
		System.out.printf(s);
		return s;
	}
}

C.java 实现类2

package herui.entity;

public class C implements A {

	@Override
	public Integer add(int a, int b) {
		return a+b+1000;
	}

	@Override
	public int sub(int a, int b) {
		return a-b-1000;
	}

	@Override
	public String print(String s) {
		if(s != null) {
			StringBuilder sBuilder = new StringBuilder(s);
			s = sBuilder.reverse().toString();
		}
		System.out.println(s);
		return s;
	}

}

示例结果:

java自定义动态代理

本文主要展示一些原理,细节并未关注