Calculator.java
1 package bhz.uts.test; 2 3 /*计算器接口*/ 4 public interface Calculator 5 { 6 public double add(double num1, double num2) throws Exception; 7 public double sub(double num1, double num2) throws Exception; 8 public double div(double num1, double num2) throws Exception; 9 public double mul(double num1, double num2) throws Exception; 10 }
ArithmeticCalculator.java
1 package bhz.uts.test; 2 3 /*计算器接口的实现类,添加记录日志功能*/ 4 public class ArithmeticCalculator implements Calculator 5 { 6 @Override 7 public double add(double num1, double num2) throws Exception 8 { 9 double result = num1 + num2; 10 11 return result; 12 } 13 14 @Override 15 public double sub(double num1, double num2) throws Exception 16 { 17 double result = num1 - num2; 18 19 return result; 20 } 21 22 /*示意代码 暂时不考虑除数0的情况*/ 23 @Override 24 public double div(double num1, double num2) throws Exception 25 { 26 double result = num1 / num2; 27 28 return result; 29 } 30 31 @Override 32 public double mul(double num1, double num2) throws Exception 33 { 34 double result = num1 * num2; 35 36 return result; 37 } 38 }
ArithmeticCalculatorInvocationHandler.java
1 package bhz.uts.test; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 import java.util.Arrays; 7 8 /*使用动态代理需要实现InvocationHandler接口*/ 9 public class ArithmeticCalculatorInvocationHandler implements InvocationHandler 10 { 11 /*要代理的对象,动态代理只有在运行时才知道代理谁,所以定义为Object类型,可以代理任意对象*/ 12 private Object target = null; 13 14 /*通过构造函数传入原对象*/ 15 public ArithmeticCalculatorInvocationHandler(Object target) 16 { 17 this.target = target; 18 } 19 20 /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/ 21 @Override 22 public Object invoke(Object proxy, Method method, Object[] args) 23 throws Throwable 24 { 25 /*原对象方法调用前处理日志信息*/ 26 System.out.println("the method ["+method.getName()+"]"+"begin with args ("+Arrays.toString(args)+")"); 27 28 Object result = method.invoke(this.target, args); 29 30 /*原对象方法调用后处理日志信息*/ 31 System.out.println("the method ["+method.getName()+"]"+"end with result ("+result+")"); 32 33 return result; 34 } 35 36 /*获取代理类*/ 37 public Object getProxy() 38 { 39 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this); 40 } 41 }
其实最关键的就是这个类在invoke方法中有代理的类对象,类的方法,有传递的参数
然后在通过调用Proxy.newProxyInstance这个方法来实现。
clent
1 package bhz.uts.test; 2 3 public class Client 4 { 5 public static void main(String[] args) throws Exception 6 { 7 /*获得代理*/ 8 Calculator arithmeticCalculatorProxy = (Calculator)new ArithmeticCalculatorInvocationHandler( 9 new ArithmeticCalculator()).getProxy(); 10 11 12 13 /*调用add方法*/ 14 arithmeticCalculatorProxy.add(10, 10); 15 } 16 }
结果
1 the method [add]begin with args ([10.0, 10.0]) 2 the method [add]end with result (20.0)
在上面的基础上其实还可以在代理的基础上在做代理如下:
ArithmeticCalculatorArgsInvocationHandler.java
1 package bhz.uts.test; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 import java.util.Arrays; 7 8 public class ArithmeticCalculatorArgsInvocationHandler implements 9 InvocationHandler 10 { 11 /*要代理的对象,动态代理只有在运行时才知道代理谁,所以定义为Object类型,可以代理任意对象*/ 12 private Object target = null; 13 14 /*通过构造函数传入原对象*/ 15 public ArithmeticCalculatorArgsInvocationHandler(Object target) 16 { 17 this.target = target; 18 } 19 20 /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/ 21 @Override 22 public Object invoke(Object proxy, Method method, Object[] args) 23 throws Throwable 24 { 25 System.out.println("begin valid method ["+method.getName()+"] with args "+Arrays.toString(args)); 26 27 for(Object arg : args) 28 { 29 this.argValidtor((Double)arg); 30 } 31 32 Object result = method.invoke(this.target, args); 33 34 return result; 35 } 36 37 /*获取代理类*/ 38 public Object getProxy() 39 { 40 return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this); 41 } 42 43 private void argValidtor(double arg) throws Exception 44 { 45 if(arg < 0) 46 throw new Exception("参数不能为负数!"); 47 } 48 }
1 package bhz.uts.test; 2 3 public class Client 4 { 5 public static void main(String[] args) throws Exception 6 { 7 /*获得代理*/ 8 Calculator arithmeticCalculatorProxy = (Calculator)new ArithmeticCalculatorInvocationHandler( 9 new ArithmeticCalculator()).getProxy(); 10 11 Calculator argValidatorProxy = (Calculator)new ArithmeticCalculatorArgsInvocationHandler(arithmeticCalculatorProxy).getProxy(); 12 13 /*调用add方法*/ 14 argValidatorProxy.add(-10, 10); 15 } 16 }
加了一个负数的校验
我们可以看到,并没有改变原来代码的逻辑,只不过是有加了一个类
调用的时候直接加一行11行的代码,然后在用返回的对象调用就可以了。
结果
1 Java HotSpot(TM) 64-Bit Server VM warning: MaxNewSize (524288k) is equal to or greater than the entire heap (524288k). A new generation size of 524224k will be used. 2 begin valid method [add] with args [-10.0, 10.0] 3 Exception in thread "main" java.lang.Exception: 参数不能为负数! 4 at bhz.uts.test.ArithmeticCalculatorArgsInvocationHandler.argValidtor(ArithmeticCalculatorArgsInvocationHandler.java:46) 5 at bhz.uts.test.ArithmeticCalculatorArgsInvocationHandler.invoke(ArithmeticCalculatorArgsInvocationHandler.java:29) 6 at com.sun.proxy.$Proxy0.add(Unknown Source) 7 at bhz.uts.test.Client.main(Client.java:14)