动态代理的基本理解与基本使用
Posted chichung
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理的基本理解与基本使用相关的知识,希望对你有一定的参考价值。
-
代理模式
代理模式,基本都懂吧。就例如我们平时去零售店买电脑。这个零售店其实就是代理商。它并不是直接生产电脑,而是帮一些生产电脑的厂商卖电脑,赚中间价。这就是代理模式。专业一点来说,在这里例子中,电脑厂就是被代理者,是真实对象。零售店就是代理者,是代理对象。代理模式就是,代理对象代理真实对象,达到增强真实对象的目的。
Java中的代理又分为静态代理与动态代理。
静态代理:简单地理解,就是有一个类文件来描述。
动态代理:在内存中形成代理类。
-
动态代理的实现步骤
(1)代理对象和真实对象实现相同的接口。
示例:
// 接口 package com.chichung.proxy; public interface SaleComputer { public String sale(double money); }
// 真实对象实现接口 package com.chichung.proxy; public class ComputerFactory implements SaleComputer { @Override public String sale(double money) { System.out.println(money+"厂家价"); return "我是厂家"; } }
(2)代理对象 = Proxy.newProxyInstance()
示例:
package com.chichung.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { ComputerFactory cf = new ComputerFactory(); // 代理对象 SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("hello"); return null; } });
} }
Proxy.newProxyInstance()参数解析:
1.类加载器:真实对象.getClass().getClassLoader()
2.接口数组:真实对象.getClass().getInterfaces()
3.处理器:new InvocationHandler(){ ... }
(3)使用代理对象调用方法
package com.chichung.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { ComputerFactory cf = new ComputerFactory(); // 代理对象 SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("hello"); return null; } }); String str = proxy_store.sale(8000); System.out.println(str); } }
输出结果:
hello
null
为什么没有真实对象的打印以及返回?不急,看下去。
先说下invoke方法的几个参数:
1.proxy:代理对象
2.method:代理对象调用的方法,被封装为对象。获取方式:method.getName()
3.args:代理对象调用方法时,传递的实际参数。获取方式:args[0]
(4)增强对象
先实现一下没有增强对象,输出结果和原来真实对象直接调用方法一样的效果。
package com.chichung.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { ComputerFactory cf = new ComputerFactory(); // 代理对象 SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = method.invoke(cf, args); // 使用真实对象调用此方法 return obj; } }); String str = proxy_store.sale(8000); System.out.println(str); } }
1.增强参数
package com.chichung.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { ComputerFactory cf = new ComputerFactory(); // 代理对象 SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("sale")){ // 增强参数 Double money = (Double) args[0]; money = money * 1.25; // 使用真实对象调用此方法 Object obj = method.invoke(cf, money); return obj; }else { // 使用真实对象调用此方法 Object obj = method.invoke(cf, args); return obj; } } }); String str = proxy_store.sale(8000); System.out.println(str); } }
输出结果:
10000.0厂家价
我是厂家
2.增强返回值
package com.chichung.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { ComputerFactory cf = new ComputerFactory(); // 代理对象 SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = method.invoke(cf, args); return obj+",一手货!!!"; } }); String str = proxy_store.sale(8000); System.out.println(str); } }
输出结果:
8000.0厂家价
我是厂家,一手货!!!
3.增强方法体
package com.chichung.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest { public static void main(String[] args) { ComputerFactory cf = new ComputerFactory(); // 代理对象 SaleComputer proxy_store = (SaleComputer) Proxy.newProxyInstance(cf.getClass().getClassLoader(), cf.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("sale")){ System.out.println("走过路过别错过"); Double money = (Double) args[0]; money = money * 1.25; // 使用真实对象调用此方法 Object obj = method.invoke(cf, money); System.out.println("手快有手慢没"); return obj; }else { // 使用真实对象调用此方法 Object obj = method.invoke(cf, args); return obj; } } }); String str = proxy_store.sale(8000); System.out.println(str); } }
输出结果:
走过路过别错过
10000.0厂家价
手快有手慢没
我是厂家
以上是关于动态代理的基本理解与基本使用的主要内容,如果未能解决你的问题,请参考以下文章
精心收集的 48 个 JavaScript 代码片段,仅需 30 秒就可理解!(转载)