面试文章中,HR问什么是静态代理?什么是动态代理?加入交流群,前往:CN.ITLTT.COM是什么代理?Java中的代理,开源理解为通过代理访问实际的目标对象,比如?我们平时买卖二手车的中间商可以算是代理,但是你也可以直接去找二手车的车主进行买卖。在这种情况下,它在Java中称为代理。代理类除了实现目标对象外,还可以为其添加很多附加功能。理论延伸:主要解决的问题:直接访问对象带来的问题,例如:要访问的对象在远程机器上。在面向对象的系统中,由于某些原因(比如对象创建成本很高,或者某些操作需要安全控制,或者需要进程外访问),直接访问会给用户或系统结构带来很多麻烦。我们可以在访问这个对象的时候给这个对象加上一个访问层。代理模式的必要条件:公共接口、代理对象、目标对象。宏观特点:只向客户端暴露接口,不暴露底层架构。优点:中间有一层隔离,更符合开闭原则。Proxy是一种?代理是一种设计模式。它不是内置函数,而是一种设计模式。在代理模式中,一个类代表另一个类的功能。这种类型的设计模式是一种结构模式。在代理模式中,我们使用现有对象创建对象,以便为外界提供功能接口。目的:为其他对象提供代理以控制对该对象的访问。代理模式的分类代理模式分为静态代理和动态代理两种实现静态代理原理不多说,还是从代码中去理解。创建一个接口首先,我们创建一个接口。一般我们每个功能都会设计一个接口,包括我们的三层架构,所以我这里也写一个接口。/***@authorJanYork*@date2022/10/258:59*@description假设Demo是买东西的界面*/publicinterfaceDemo{/***买东西*@paramname东西的名字*@paramprice东西的价格*@return买东西的结果*/Stringbuy(Stringname,intprice);}那我们假设这个Demo是一个买东西的界面。它还提供了一种简单的购买方式(实际上是输出测试)。要实现接口,就要实现这个接口,也就是我们的接口实现类。/***@authorJanYork*@date2022/10/259:03*@descriptionRealDemo类(代理类)*/publicclassRealDemoimplementsDemo{publicRealDemo(Stringname,intprice){this.名字=名字;这个。价格=价格;}私有字符串名称;私人价格;@OverridepublicStringbuy(Stringname,intprice){System.out.println("Buy"+name+"Spent"+price+"yuan");return“买的”+名字+“花的”+价格+“元”;}}给他两个参数,一个结构体,然后重写接口提供的方法,这个就不用说了。代理类/***@authorJanYork*@date2022/10/259:05*@descriptionDemo的代理类*/publicclassProxyDemoimplementsDemo{privateRealDemorealDemo;publicProxyDemo(Stringname,intprice){this.realDemo=newRealDemo(name,price);}@OverridepublicStringbuy(Stringname,intprice){System.out.println("-----代理类开始买东西-----");Stringresult=realDemo.buy(name,price);System.out.println("------代理类购买结束------");返回结果;}}创建好代理后,我们还需要实现这个Demo接口。然后需要注入实现接口的类(也就是真正的类)的对象。私有真实演示真实演示;然后实现结构:publicProxyDemo(Stringname,intprice){this.realDemo=newRealDemo(name,price);}然后在重写的方法中调用它,调用方法前后可以做一些事情。然后我们创建一个Test类测试:StaticProxyDefects问:静态代理既然可以轻松达到目的,那么它有什么缺点吗?静态代理需要在代码运行之前创建一个代理类,所以对于每一个代理对象,都需要创建一个代理类来进行代理。如果需要代理很多对象,就需要创建很多代理类,降低程序的可维护性。Q:那么如何解决这个缺陷呢?动态构建代理类,即动态代理。动态代理动态代理的代理类是在运行过程中生成的。Java提供了两种实现动态代理的方式:基于JDK的动态代理。基于Cglib的动态代理。特点:字节码可以在使用时创建和加载。功能:在不修改源代码的情况下增强方法。基于JDK实现Jdk的动态代理需要实现InvocationHandler接口,然后实现其中的invoke方法。我们创建一个实现InvocationHandler(来自java.lang.reflect反射包)接口的类。在这个分类下,有非常丰富和详细的解释,大家可以看看。实现接口后,我们用Object来替换原来静态代理类中的这一段:privateRealDemorealDemo;publicProxyDemo(Stringname,intprice){this.realDemo=newRealDemo(name,price);}就是这样:privateObjecttarget;publicProxyHandler(Objecttarget){this.target=target;}然后覆盖调用方法:@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println("-----动态代理启动------");对象调用=method.invoke(target,args);System.out.println("------动态代理结束------");returninvoke;}里面有多个参数,后面会解释。调用首先仍然创建真实对象并给出结构。RealDemorealDemo=newRealDemo("Apple",10);然后创建一个动态代理对象并将正式对象传递给它。ProxyHandlerproxyHandler=newProxyHandler(realDemo);然后我们调用,其实就是使用Proxy类调用newProxyInstance方法。Proxy.newProxyInstance(realDemo.getClass().getClassLoader(),realDemo.getClass().getInterfaces(),proxyHandler);此方法是具有以下参数的静态方法。newProxyInstance(ClassLoaderloader,Class>[]interfaces,InvocationHandlerh)第一个是类加载器,第二个是泛型Class数组,需要接口,第三个参数也是InvocationHandler对象的实现。那么我们调用时给的参数是://获取真实类的类加载器realDemo.getClass().getClassLoader(),//获取真实类实现的接口realDemo.getClass().getInterfaces(),//实现InvocationHandler接口的对象proxyHandler,对于反射的知识有很多设计。看不懂建议折腾。然后我们调用动态对象的方法如下:",10);//调用动态代理RealDemorealDemo=newRealDemo("Apple",10);ProxyHandlerproxyHandler=newProxyHandler(realDemo);演示demo=(Demo)Proxy.newProxyInstance(realDemo.getClass().getClassLoader(),realDemo.getClass().getInterfaces(),proxyHandler);demo.buy("苹果",10);}}Proxy.newProxyInstance方法返回一个Object,我们将它转??化为我们的接口对象。然后通过对象调用相应的方法。效果优势一个动态代理可以作用于N个需要被代理的对象,只需要将代理类的参数放入Proxy.newProxyInstance方法即可。缺陷JDK只能代理接口!JDK动态代理只能代理接口。JDK动态代理是基于接口的。也就是说,代理类和目标类都实现了同一个接口。如果你想要一个代理类,你可以使用CGLib。CGLib动态代理是代理类继承目标类,然后实现目标类的方法。基于CGLib实现,首先引入依赖:
