1.目标接口
package org.example.proxy; public interface Calculator { int add(int i, int j); int sub(int i, int j); int mul(int i, int j); int div(int i, int j); }
2.目标实现
package org.example.proxy; public class CalculatorPureImpl implements Calculator { @Override public int add(int i, int j) { int result = i + j; System.out.println("方法内部 result = " + result); return result; } @Override public int sub(int i, int j) { int result = i - j; System.out.println("方法内部 result = " + result); return result; } @Override public int mul(int i, int j) { int result = i * j; System.out.println("方法内部 result = " + result); return result; } @Override public int div(int i, int j) { int result = i / j; System.out.println("方法内部 result = " + result); return result; } }
3.代理工厂
public class LogDynamicProxyFactory { // 将被代理的目标对象声明为成员变量 private Calculator target; public LogDynamicProxyFactory() { } public LogDynamicProxyFactory(Calculator target) { this.target = target; } public Calculator getProxy() throws Throwable { // 创建代理对象所需参数一:加载目标对象的类的类加载器 ClassLoader classLoader = target.getClass().getClassLoader(); // 创建代理对象所需参数二:目标对象的类所实现的所有接口组成的数组 Class<?>[] interfaces = target.getClass().getInterfaces(); InvocationTest handler = new InvocationTest() { @Override public Object Objectinvoke(Method method, Object[] args){ // 代理对象,当前方法用不上这个对象 // method就是代表目标方法的Method对象 // 外部调用目标方法时传入的实际参数 // 我们对InvocationHandler接口中invoke()方法的实现就是在调用目标方法 // 围绕目标方法的调用,就可以添加我们的附加功能 // 声明一个局部变量,用来存储目标方法的返回值 Object targetMethodReturnValue = null; // 通过method对象获取方法名 String methodName = method.getName(); // 为了便于在打印时看到数组中的数据,把参数数组转换为List List<Object> argumentList = Arrays.asList(args); try { // 在目标方法执行前:打印方法开始的日志 log.debug("[动态代理][日志] " + methodName + " 方法开始了,参数是:-----" + argumentList); // 调用目标方法:需要传入两个参数 // 参数1:调用目标方法的目标对象 // 参数2:外部调用目标方法时传入的实际参数 // 调用后会返回目标方法的返回值 targetMethodReturnValue = method.invoke(target, args); // 在目标方法成功后:打印方法成功结束的日志【寿终正寝】 log.debug("[动态代理][日志] " + methodName + " 方法成功结束了,返回值是:-----" + targetMethodReturnValue); }catch (Exception e){ // 通过e对象获取异常类型的全类名 String exceptionName = e.getClass().getName(); // 通过e对象获取异常消息 String message = e.getMessage(); // 在目标方法失败后:打印方法抛出异常的日志【死于非命】 log.debug("[动态代理][日志] " + methodName + " 方法抛异常了,异常信息是:-----" + exceptionName + "," + message); }finally { // 在目标方法最终结束后:打印方法最终结束的日志【盖棺定论】 log.debug("[动态代理][日志] " + methodName + " 方法最终结束了-----"); } // 这里必须将目标方法的返回值返回给外界,如果没有返回,外界将无法拿到目标方法的返回值 return targetMethodReturnValue; } }; // org.example.dss.Calculator proxy = (Calculator) Proxy.newProxyInstance(classLoader, interfaces, handler); Calculator calculator = (Calculator) MyProxyTest.myGetPorxyInstance(classLoader, interfaces, handler); // 返回代理对象 return calculator; } }
4.代理
public class MyProxyTest { public static Object myGetProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationTest h) throws Throwable { Class<?>[] clone = interfaces.clone(); Class<?> aClass = loader.loadClass(interfaces.clone()[0].getName()); Method[] methods = aClass.getMethods(); HashMap<String, Method> map = new HashMap<>(); String mm = ""; for (Method method : methods){ String name = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); map.put(name,method); String m = " public int "+ name+ "("+parameterTypes[0].getName()+" i, "+parameterTypes[1].getName()+" j)" + " {" + " Object objectinvoke = h.Objectinvoke(this.methods.get(\""+name+"\"), new Object[]{i,j});" + " return (int)objectinvoke;" + " }"; mm = mm + m; } //------------------------------------------------------------------"package org.example.proxy;" + // 传入String类型的代码 String source = "import java.util.HashMap;import java.lang.reflect.Method;\n" + "\n" + "\n" + "public class ProxyCal implements Calculator\n" + "{\n" + " private InvocationTest h;\n" + " private HashMap<String, Method> methods;\n" + "\n" + " public ProxyCal() {\n" + " }\n" + " public ProxyCal(InvocationTest h) {\n" + " this.h = h;\n" + " }\n" + " public InvocationTest getH() {\n" + " return this.h;\n" + " }\n" + "\n" + " public void setH(InvocationTest h) {\n" + " this.h = h;\n" + " }\n" + " @Override\n"+ mm + "}"; Class<?> clazz = (Class<?>)StringCompiler.run(source, "1", "2"); Constructor<?>[] constructors = clazz.getConstructors(); Object instance = constructors[1].newInstance(h); Field fieldMethod = clazz.getDeclaredField("methods"); fieldMethod.setAccessible(true); fieldMethod.set(instance,map); return instance; } }
5.测试
public class test1 { @Test public void test1() throws Throwable { // 1.创建被代理的目标对象 Calculator target = new CalculatorPureImpl(); LogDynamicProxyFactory proxyFactory = new LogDynamicProxyFactory(target); Calculator proxy = proxyFactory.getProxy(); System.out.println(proxy.add(3, 3)); System.out.println(proxy.sub(3, 3)); System.out.println(proxy.mul(3, 3)); System.out.println(proxy.div(3, 3)); } }
参数的数量,类型,肯定是不一样的,但是都是可以拿到的,无非拼接是麻烦一些,我就懒得搞了
标签:int,Calculator,代理,目标,result,简单,动态,方法,public From: https://www.cnblogs.com/dzs894330350/p/16840196.html