>不用代理
有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码。
这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果。(至于为什么不直接用+号运算,见【Java】Float计算不准确)
package com.nicchagil.study.java.demo.No09代理.No01不用代理; import java.math.BigDecimal; public class FloatCalculator { public float add(float a, float b) { BigDecimal b1 = new BigDecimal(a + ""); BigDecimal b2 = new BigDecimal(b + ""); float f = b1.add(b2).floatValue(); return f; } }
我想在它运行前后打印,最直接的方式就是调用时打印了
package com.nicchagil.study.java.demo.No09代理.No01不用代理; public class Call { public static void main(String[] args) { float f1 = 1f; float f2 = 1f; System.out.println("f1 -> " + f1 + ", f2 -> " + f2); float result = new FloatCalculator().add(f1, f2); System.out.println("result -> " + result); } }
看到这日志,我很欣慰!
f1 -> 1.0, f2 -> 1.0 result -> 2.0
>静态代理
随着项目变大,调用此方法的地方变得越来越多,如果有10个调用的地方,我岂不是要写100次打印的方法。
这时,静态代理的方式能帮助我们。
定义个接口
package com.nicchagil.study.java.demo.No09代理.No02静态代理; public interface ICalculator { /** * <p>add</p> */ public float add(float a, float b); }
真实业务类
package com.nicchagil.study.java.demo.No09代理.No02静态代理; import java.math.BigDecimal; public class FloatCalculator implements ICalculator { @Override public float add(float a, float b) { BigDecimal b1 = new BigDecimal(a + ""); BigDecimal b2 = new BigDecimal(b + ""); float f = b1.add(b2).floatValue(); return f; } }
代理类,这个类中,处理执行实际业务,还一并捆绑打印日志的任务
package com.nicchagil.study.java.demo.No09代理.No02静态代理; public class FloatCalculatorProxy implements ICalculator { ICalculator c = null; /** * 构造方法 * @param c 需被代理的对象 */ public FloatCalculatorProxy(ICalculator c) { super(); this.c = c; } @Override public float add(float f1, float f2) { System.out.println("f1 -> " + f1 + ", f2 -> " + f2); float result = this.c.add(f1, f2); System.out.println("result -> " + result); return result; } }
然后,我们调用时,只需调用代理类,不仅计算得结果,日志也乖乖地出来了
package com.nicchagil.study.java.demo.No09代理.No02静态代理; public class Call { public static void main(String[] args) { System.out.println("代理的对象:"); ICalculator c2 = new FloatCalculatorProxy(new FloatCalculator()); c2.add(1f, 1f); } }
看到日志,我很镇静
代理的对象: f1 -> 1.0, f2 -> 1.0 result -> 2.0
>动态代理
如果现在不仅FloatCalculator这个类需要打印日志,还有其他各种类也需要打印日志,那么我们岂不是要写好多个代理类了?
这时候,Java API拍案而起,提出动态代理。通过反射机制为我们实现动态代理。
接口类(ICalculator)、真实业务类(FloatCalculator)如同静态代理,不再重复
调用处理类
package com.nicchagil.study.java.demo.No09代理.No03动态代理; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class DynamicProxyHandler implements InvocationHandler { private Object proxied = null; public DynamicProxyHandler(Object proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Clazz -> " + proxy.getClass()); System.out.println("method -> " + method); for (int i = 0; i < args.length; i++) { System.out.println("args[" + i + "] -> " + args[i]); } Object result = method.invoke(proxied, args); System.out.println("result -> " + (result != null ? result.toString() : "")); return result; } }
调用类
package com.nicchagil.study.java.demo.No09代理.No03动态代理; import java.lang.reflect.Proxy; import com.nicchagil.study.java.demo.No09代理.No02静态代理.FloatCalculator; import com.nicchagil.study.java.demo.No09代理.No02静态代理.ICalculator; public class Call { public static void main(String[] args) { /* 代理的对象 */ System.out.println("代理的对象:"); ICalculator c2 = (ICalculator)Proxy.newProxyInstance(ICalculator.class.getClassLoader(), new Class[] {ICalculator.class}, new DynamicProxyHandler(new FloatCalculator())); c2.add(1f, 1f); } }
日志
代理的对象: Clazz -> class $Proxy0 method -> public abstract float com.nicchagil.study.java.demo.No09代理.No02静态代理.ICalculator.add(float,float) args[0] -> 1.0 args[1] -> 1.0 result -> 2.0
暂时完毕。
时间: 2024-10-23 16:22:29