java代理模式静态代理与动态代理Arebirth

在学习代理模式的时候我首先要提出几个问题,

1、什么是代理模式?

举个例子吧:我们生活中的租房问题。假如我们去租个房子,我们大多数情况下是不会知道房主(就是真正租房,一手货源)的,我们是不是都是先去某些租房平台,或者去找当地的中介去询问何时的房子。我们通过九牛二虎之力在中介那里找到了个物美价廉的房子后,你的租金是不是交给了中介,中介还会收取一些额外的推荐费啦,押金啦、手续费等之类的,那么好,这样的一小段,就已经出来了其中两大核心对象了。

房主(把房子交给中介的人):被代理对象

中介(租给你房子的人):代理对象

2、代理模式有哪些作用?

1.可以隐藏目标的的具体实现(还是拿上面租房的例子来说,房主把房子交给了中介,并和中介谈好了价格我7你3啊。然后当我们去租房子的时候,是中介正面把房子租给了我们,而真正背后卖房子的并未出面,这样就隐藏了背后人的信息和提高了背后人的安全)

2.可以在不修改目标类代码的情况下,对其增加新的功能。(上面例子来说:房东把房子交给中介的时候价格可能只有1000,但是房东可以卖到5000,然后卖出去后在把1000给房东,自己收入4000,这样原房东不但收到了应由的钱,中介还收入了更多的额外费用)。

3、代理模式有哪几种?分别都有什么不同?

在我们Java程序中代理模式分为:静态代理和动态代理(动态代理又分为:JDK动态代理和CGLIB动态代理)

至于什么不同,接下来正式我们着重要学习的内容

什么是静态代理呢?

具体实现:

被代理类与代理类共同实现的接口

packagecn.arebirth.staticproxy;/***需要实现的共同接口*因为要保证代理类要不改变被代理类原来功能的基础上增加新的功能*/publicinterfaceRentalHouse{/***出租房子*/voidrent();}被代理类(房东)

packagecn.arebirth.staticproxy;/***房东(目标类、被代理类)*/publicclassHostimplementsRentalHouse{@Overridepublicvoidrent(){System.out.println("我是房东,出租500平米的大房子");}}代理类(中介)

packagecn.arebirth.staticproxy;/***静态代理类(中介、代理类)*注意:需要被代理类实现相同的接口*/publicclassStaticProxyimplementsRentalHouse{privateRentalHouserentalHouse;publicStaticProxy(RentalHouserentalHouse){this.rentalHouse=rentalHouse;}@Overridepublicvoidrent(){System.out.println("我是中介,收你500推荐费");//调用被代理类的租房方法rentalHouse.rent();System.out.println("我是中介,我又想收你1000块钱!");}}测试类

packagecn.arebirth.staticproxy;publicclassTest{publicstaticvoidmain(String[]args){//创建被代理度下行Hosthost=newHost();/***创建代理对象,并把被代理对象传递给代理对象,*因为他们都实现相同的接口,实现了相同的方法,这样的话传递的对象可以是房东1房东2...*/StaticProxyproxy=newStaticProxy(host);proxy.rent();}}输出结果:我是中介,收你500推荐费我是房东,出租500平米的大房子我是中介,我又想收你1000块钱!

试想一下,如果有两个房东,三个,四个,甚至更多个房东的话,我们怎么写?

被代理类

packagecn.arebirth.staticproxy;/***房东1(目标类、被代理类)*/publicclassHost1implementsRentalHouse{@Overridepublicvoidrent(){System.out.println("我是房东1,出租500平米的大房子");}}packagecn.arebirth.staticproxy;/***房东2(目标类、被代理类)*/publicclassHost2implementsRentalHouse{@Overridepublicvoidrent(){System.out.println("我是房东2,出租500平米的大房子");}}

代理类(中介)

packagecn.arebirth.staticproxy;/***静态代理类(中介、代理类)*注意:需要被代理类实现相同的接口*/publicclassStaticProxyimplementsRentalHouse{//什么价位的房子privateintmoneuy;publicAgent(intmoneuy){this.moneuy=moneuy;}@Overridepublicvoidrenting(){//出租房东的租房//中介调用的租房方法仍然是房东的租房方法System.out.println("收取50元推荐费");if(moneuy<=800){//金额小于等于800的时候Host1host=newHost1();host.rent();}else{Host2host=newHost2();host.rent();}System.out.println("收取500元押金费用");}}测试类

publicclassTest{publicstaticvoidmain(String[]args){StaticProxyproxy=newStaticProxy(1000);proxy.renting();}}输出结果:我是房东2,出租500平米的大房子

静态代理的缺点:

我们仔细来观察下,随着我们的被代理对象的增多,也是就是房东越来越多,那我们的被代理类就会越来越冗余,中介的压力也就会越来越大。

常用的动态代理又分为JDK动态代理和CGLIB动态代理

那么两者的使用场景又是什么呢??

如果目标对象实现了接口,就是上面我们举到的例子,房东和中介共同实现的接口类似,这样的话就采用JDK动态代理

如果目标对象没有实现接口,必须采用CGLIB动态代理

要实现的共同接口

packagecn.arebirth.jdkproxy;/***需要实现的共同接口*/publicinterfaceRentalHouse{/***出租房子*/voidrent();}房东(被代理对象)

packagecn.arebirth.jdkproxy;/***房东(目标类、被代理类)*/publicclassHostimplementsRentalHouse{@Overridepublicvoidrent(){System.out.println("我是房东,出租500平米的大房子");}}核心来了!(JDK动态代理实现类)packagecn.arebirth.jdkproxy;

packagecn.arebirth.jdkproxy;publicclassTest{publicstaticvoidmain(String[]args){//创建JdkProxy动态代理对象类,并把需要被代理的对象传递进去JdkProxyjdkProxy=newJdkProxy(newHost());//获得代理类这里一定要写他们共同实现的接口利用java多态的特性,如果直接写真实类型是会报错的RentalHouseproxy=(RentalHouse)jdkProxy.getProxy();proxy.rent();}}输出结果:我是中介,收你500推荐费我是房东,出租500平米的大房子我是中介,我又想收你1000块钱!

我想当你看到这里一定会感到困惑,为什么我们获取到了代理对象后执行的执行代理对象的方法,明明是房东的方法,怎么显示的好像是JDK动态代理类里面的invoke()方法??或许还有其他的困惑,我们将在下边一一讲解如何实现的原理。

既然想知道如何实现的,那么我们就要从底层出发,来看看,底层的Proxy代理到底帮我们生成了一个怎样的代理类。

再开始之前我希望接下来的代码与操作你是跟着我同步进行的,这样子才会更深刻有更好的理解,当然不排除你是个人脑机器模拟器

开始吧!

我们想要看底层如何实现的,那么我们首先就要获得代理类的class文件

下面是我写的一个获取JDKProxy动态代理所生成的代理文件的工具类

packagecn.arebirth.jdkproxy;importsun.misc.ProxyGenerator;importjava.io.File;importjava.io.FileOutputStream;importjava.io.FileWriter;importjava.io.IOException;publicclassProxyUtil{/***@paramproxyName生成文件代理类的名字*@paraminterClass代理类所实现的接口的class数组形式*@parampath写出路径*/publicstaticvoidwriteProxyClassToHardDisk(StringproxyName,Class[]interClass,Stringpath){byte[]bytes=ProxyGenerator.generateProxyClass(proxyName,interClass);FileOutputStreamout=null;try{out=newFileOutputStream(path+File.separator+proxyName+".class");out.write(bytes);out.flush();}catch(IOExceptione){e.printStackTrace();}finally{try{if(out!=null)out.close();}catch(IOExceptione){e.printStackTrace();}}}}然后我们在测试类里面使用它

packagecn.arebirth.jdkproxy;publicclassTest{publicstaticvoidmain(String[]args){//创建JdkProxy动态代理对象类,并把需要被代理的对象传递进去JdkProxyjdkProxy=newJdkProxy(newHost());//获得代理类RentalHouseproxy=(RentalHouse)jdkProxy.getProxy();proxy.rent();//写入JDK动态代理生成的代理类ProxyUtil.writeProxyClassToHardDisk(proxy.getClass().getSimpleName(),proxy.getClass().getInterfaces(),"F:\\Tools\\DevelopmentTools");}}

最后生成出来的代理类是一个class字节码文件,我们需要使用反编译工具来查看,我使用的是Luten(这个工具打开方式特殊,百度自行查找)

super.h.invoke(this,$Proxy0.m3,null);那么super是谁?就是它自动继承的Proxy类

那么h是什么?就是Proxy类的InvocationHandler

那么我们看这个InvocationHandler类是不是感觉有那么一丢丢的眼熟啊,回过头看,这就是我们在写JDK动态代理类的时候实现的那个接口。

!!!!!!!!!!!!!

然后它又调用了invoke(this,$Proxy0.m3,null);

第一个参数:代理类对象

第二个参数:要执行的代理类对象的方Method对象,这个Method对象的值已经由我们的编译器帮我们构建好了,我们只需要第一个次加载这个类的时候他就会自动赋值了(static代码块)

第三个参数:方法里面的参数,当没有参数的时候就是NULL

带着你的疑惑,从头在开始好好敲一遍代码,捋一遍,相信我,你将有更大的收货!!

下面是简略画的思路图,试着用画图来画出你的思维

是不是这个JDK动态代理必须要依赖接口才能实现,如果没有接口的话,那么JDK动态代理也就凉凉了对吧,!

那么好,接下来我们将说一种更加强大的动态代理方式CGLIB,它的实现原理只要我们懂了JDK动态代理,那么下面的就是小儿科啦哈哈~

CGLIB的代理将不再需要接口也可以生成代理类,但是它需要导包!

当然,你也可以选择其他版本的JAR包!

===

开始

packagecn.arebirth.cglibproxy;/***被代理类*/publicclassHost{publicvoidrent(){System.out.println("Host:rentalhouse");}}生成代理对象的cglib类

packagecn.arebirth.cglibproxy;importnet.sf.cglib.proxy.Enhancer;importnet.sf.cglib.proxy.MethodInterceptor;importnet.sf.cglib.proxy.MethodProxy;importjava.lang.reflect.Method;publicclassCglibProxyimplementsMethodInterceptor{/***获取代理类**@return*/publicObjectgetProxy(){Enhancerenhancer=newEnhancer();//设置被代理对象enhancer.setSuperclass(Host.class);//设置回调方法当前对象enhancer.setCallback(this);//创建代理对象Objecto=enhancer.create();returno;}/***@paramo被代理对象*@parammethod被代理对象方法*@paramobjects被代理对象方法中的参数*@parammethodProxy代理类中的方法*@return*@throwsThrowable*/@OverridepublicObjectintercept(Objecto,Methodmethod,Object[]objects,MethodProxymethodProxy)throwsThrowable{System.out.println("中介收取手续费");Objecto1=methodProxy.invokeSuper(o,objects);System.out.println("中介收取中介费");returno1;}}测试类

packagecn.arebirth.cglibproxy;publicclassTest{publicstaticvoidmain(String[]args){CglibProxycglibProxy=newCglibProxy();Hostproxy=(Host)cglibProxy.getProxy();//强制转换为我们的房主proxy.rent();}}输出结果:中介收取手续费Host:rentalhouse中介收取中介费

我们动态代理的最大好处就是,可以在没有接口的情况下,只有一个类,我们就可以动态的代理,在程序运行的时候动态的为他创建代理类

最后让我们大概的总结下:

代理模式:静态代理动态代理:JDK动态代理CGLIB动态代理

代理模式的三个要素A.抽象的类或接口完成一件怎样的事情B被代理对象事情操作具体内容C代理对象帮助我们完成事情的同时可以增加其他的东西

具体的列子:我们找中介租房子A抽象的类或者接口租房子B被代理对象房东C代理对象中介

代理模式的好处A房东可以安心的做自己的事情(被代理对象可以做自己的事情)B我们有了问题可以直接找中介(被代理对象变得比较安全)C可以增强代码的扩展性

JDK动态代理和CGLIB动态代理的使用场景

我们可以这样记一下,只要被代理类没有实现接口,我们就必须使用CGLIB动态代理

THE END
1.找中介买房有啥好处?找中介买房有哪些风险?找中介买房有啥好处?找中介买房有哪些风险? 现在很多人买房都是找中介,找房产中介买房可以省去很多时间和精力,得到专业、全面的服务,同时还能有一定的安全保障。 及时楼市资讯,就上楼盘网 长按识别二维码,查看详情! 现在很多人买房都是找中介,找房产中介买房可以省去很多时间和精力,得到专业、全面的服务,同时还能有https://m.loupan.com/ty/news/202007/5221651
2.“中介”买房和“售楼处”买房有什么区别?售楼部开发商房地产房首先就新开的楼盘而言,并不存在中介,中介是二手房才有的,新房是内场代理,就是售楼部工作人员,还有外场代理,主要是渠道商,但是,很多时候内外场代理都是一家代理公司。开发商由于考虑成本和效率,很少会有自己的销售团队,基本上都让几家大的渠道代理商销售,以降低成本提高效率。现在房地产销售市场,超过80%的售楼部都https://www.163.com/dy/article/J0JVMFCI0540SN7V.html
3.我想买房子找中介好吗公司是非常重要的,一定要选择当地信誉度非常高的中介,防止上当受骗,找中介买房的好处就是,中介的人脉是非常广的,很快就能找到合适自己的房子,并且中介公司会帮忙拟定购房合同,完全不用担心卖方在购房合同上面玩小聪明,但是拜托中介买房的话,是需要支付一部分费用给中介的,不想支付费用的朋友,可以到售房网站购买房子。https://m.jia.com/wenda/mip/a-577389.html
4.找中介租房的流程是怎样的?租房找中介的好处有哪些?我们在大城市找工作,首先要解决的就是租房问题。租房的话一般都是通过找中介,那么今天就给大家说说,租房找中介的好处有哪些?这个问题。 1、中介房源比较多,可供挑选,省了到处奔忙看房和到处找房源之苦。 2、中介会和房东协商好价格、压金、租金之类,租客只要对中介表达自己的意思即可,不用自己去直接面对房东讨价https://m.loushi.com/huizhou/zixun/28708.html
5.二手房是不是一定要找中介?找中介买房有哪些好处?买二手房的问题有很多,纠纷也是很多的,其实面对纠纷的问题大多数对于房产并不是很了解,一般买二手房都是通过中介吗的,但是中介的费用按时很高的,所以有的人想不通过中介,这样就节省了一部分的费用,当了不找中介其他的渠道也是很多的。那么小编就来告诉你二手房是不是一定要找中介?找中介买房有哪些好处? https://zhishi.fang.com/xf/qg_1031881.html
6.通过中介租房子有什么好处通过中介租房有哪些好处 1、找中介租房好处是可能会缩短找房客的时间,因为他们的信息比较多。2、如果你在网上贴信息,如果说不出中介费的话,很大的可能是被人删掉,因为房地产中介对信息的控制比较强。 10w+浏览 房产纠纷 房东租给中介,中介租给我。结果中介跑了我房子还能租吗 [律师回复] 要看房东和中介签的什https://mip.64365.com/zs/776281.aspx
7.通过中介租房子有什么好处吗律师普法通过中介租房子有什么好处吗2021-03-11 366 普法内容通过中介租房子的好处有: 1、中介房源信息广泛,可以快速筛选合适的房源,求租率较高; 2、出租有保障,中介具有专业的经验,可以有效避免风险保障租客的人身财产安全; 3、换租方便,中介对当地房源知之甚深,租客紧急换租较为方便。https://www.110ask.com/tuwen/13916019681285160289.html
8.2024最新马来西亚租房攻略(租房流程+途径+租房网站/App+价格+注意没有家具(Unfurnished)的房子:租金最便宜的,但也是最不方便的,因为屋主通常只提供最基本的橱柜、沙发和桌子等家具而已,有的甚至只是一间空房。 Step 3:开始找房 你可以找中介帮你物色合适的房子,经验丰富的房地产经纪绝对可以为你争取到最好的交易条件,并且能在最大程度维护你的利益。当然你也可以自己找,找房源https://www.extrabux.cn/chs/guide/7175043
9.中介买房子,然后她的中介费太高了我又另外找的中介这种行为违法吗中介以下行为会受处罚:利用信息不对称隐瞒真实价格;捏造散布涨价信息;以隐瞒、欺诈、胁迫、贿赂等不正当https://www.findlaw.cn/wenda/q_37990289.html