初学Java代理机制,看了好几篇博客终于有点感觉,用我自己的理解写了篇总结,如有不对的地方,欢迎大佬指正。
什么是代理
我的理解就是给这段程序请了一个”经纪人”,执行的时候还是这段程序来执行,只不过前后有些事务可以交给”经纪人”打理,就像明星的经纪人一样,帮明星打理一些事情,唱歌、演戏还得由明星自己去做。
静态代理
我以主播为例。
主播最主要的工作就是直播,所以定义一个接口。
1 2 3
| interface Streamer { public void work(); }
|
主播里面主要有游戏主播,唱歌主播等,所以先定义两个类实现主播这个接口
1 2 3 4 5 6 7 8 9 10 11 12 13
| class GameStreamer implements Streamer{ @Override public void work() { System.out.println("直播打游戏"); } }
class SingerStreamer implements Streamer{ @Override public void work() { System.out.println("直播唱歌"); } }
|
好了,现在游戏主播越来越火,需要处理的事情也越来越多,比如:签合同,抽奖,微博、公众号互动,开淘宝店等等。他觉得很烦,所以请了个经纪人或者找了一个公司又或者组了个团队,总之就是一个代理,专门帮他运营这些杂事,他就只负责做好直播就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class StreamerProxy implements Streamer{ private Streamer streamer;
public StreamerProxy(Streamer streamer){ this.streamer = streamer; } @Override public void work() { beforeWork(); streamer.work(); afterWork(); } private void beforeWork(){ System.out.println("帮客户签合同"); System.out.println("发布公告"); } private void afterWork(){ System.out.println("抽奖"); System.out.println("开淘宝店"); } }
|
测试类
1 2 3 4 5 6 7
| public class ProxyTest { public static void main(String[] args) { Streamer gameStreamer = new GameStreamer(); StreamerProxy streamerProxy = new StreamerProxy(gameStreamer); streamerProxy.work(); } }
|
结果
1 2 3 4 5
| 帮客户签合同 发布公告 直播打游戏 抽奖 开淘宝店
|
同样,不管是什么主播,唱歌主播,还是户外主播,只要他找了代理,就能帮他完成除直播外的一些额外的主播之间相同的工作。
当然,代理想要赚更多钱。你不是主播,你有流量,我也可以帮你做这些事啊。不过,就要重新按照上面的流程,定义接口,实现类,定义代理,再来一遍,但是代理做的工作是一样的。为了减少代码量,实现灵活处理,就有了动态代理。
动态代理
动态代理有两种实现方法,一种是JDK自带的,通过实现InvocationHandler接口,另一种是采用开源项目cglib。
JDK动态代理
定义另外一个微博大V接口及实现类
1 2 3 4 5 6 7 8 9 10 11 12
| interface WeiboBigV{ public void post(); }
class BeautyBigV implements WeiboBigV{ @Override public void post() { System.out.println("上传美照"); } }
|
实现InvocationHandler接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class DynamicProxy implements InvocationHandler {
private Object person; public DynamicProxy(Object person) { this.person = person; } public Object getNewInstance() { return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeWork(); Object object = method.invoke(person,args); afterWork(); return object; } private void beforeWork() { System.out.println("帮客户签合同"); System.out.println("发布公告"); } private void afterWork() { System.out.println("抽奖"); System.out.println("开淘宝店"); } }
|
测试类
1 2 3 4 5 6 7 8 9 10 11
| public class ProxyTest { public static void main(String[] args) { DynamicProxy dynamicProxy = new DynamicProxy(new GameStreamer()); Streamer streamer = (Streamer) dynamicProxy.getNewInstance(); streamer.work(); System.out.println("---------------------------"); dynamicProxy = new DynamicProxy(new BeautyBigV()); WeiboBigV weiboBigV = (WeiboBigV) dynamicProxy.getNewInstance(); weiboBigV.post(); } }
|
实现结果
1 2 3 4 5 6 7 8 9 10 11
| 帮客户签合同 发布公告 直播打游戏 抽奖 开淘宝店 --------------------------- 帮客户签合同 发布公告 上传美照 抽奖 开淘宝店
|
cglib动态代理
cglib动态代理和JDK动态代理最大区别就是不用定义接口。
需要手动导入cglib-nodep-xxx.jar
定义两个类,不用实现相应接口
1 2 3 4 5 6 7 8 9 10 11
| class AnotherGameStreamer{ public void work(){ System.out.println("不用实现接口就可以直播打游戏"); } }
class AnotherBeautyBigV { public void post(){ System.out.println("不用实现接口就可以上传美照"); } }
|
实现MethodInterceptor接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer(); @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { beforeWork(); Object object = methodProxy.invokeSuper(o, objects); afterWork(); return object; } private void beforeWork() { System.out.println("帮客户签合同"); System.out.println("发布公告"); } private void afterWork() { System.out.println("抽奖"); System.out.println("开淘宝店"); } public Object getNewInstance(Class c) { enhancer.setSuperclass(c); enhancer.setCallback(this); return enhancer.create(); } }
|
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class ProxyTest { public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy(); AnotherGameStreamer anotherGameStreamer = (AnotherGameStreamer) cglibProxy.getNewInstance(AnotherGameStreamer.class); anotherGameStreamer.work(); System.out.println("------------------------------"); AnotherBeautyBigV anotherBeautyBigV = (AnotherBeautyBigV) cglibProxy.getNewInstance(AnotherBeautyBigV.class); anotherBeautyBigV.post(); } }
|
实现结果
1 2 3 4 5 6 7 8 9 10 11
| 帮客户签合同 发布公告 不用实现接口就可以直播打游戏 抽奖 开淘宝店 ------------------------------ 帮客户签合同 发布公告 不用实现接口就可以上传美照 抽奖 开淘宝店
|
参考
Java静态代理&动态代理笔记
Java Proxy 和 CGLIB 动态代理原理