(二十四)(项目篇)Netty准备之动态代理

时间:2022-02-11 08:56:16

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)