当前位置:首页 > CN2资讯 > 正文内容

静态代理和动态代理区别(是否有实现类)

19小时前CN2资讯



文章目录

  • 一、简介
  • 1、代理分类:
  • 2、代码区别:
  • 二、静态代理
  • 1、接口定义要做的事情
  • 2、具体用户实现类
  • 3、代理类(业务增强类)
  • 4、测试类
  • 三、动态代理
  • 1、JDK动态代理类
  • 1.1、有接口有委托类的情况
  • 1.2、仅有接口的情况
  • 2、CGLIB动态代理
  • 三、总结



一、简介

Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题,

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。

Java中使用代理技术主要用于扩展原功能又不侵入(修改)源代码
主要应用: 比如想在某个类的某个方法执行之前打印日志或者记录下开始时间,但是又不好将打印日志和时间的逻辑写入原来的方法里。这时就可以创建一个代理类实现和原方法相同的方法,通过让代理类持有真实对象,然后代码调用的时候直接调用代理类的方法,来达到增强业务逻辑的目的。

1、代理分类:

静态代理: 由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。

Java中的静态代理要求代理类(ProxySubject)和委托类(RealSubject)都实现同一个接口(Subject)。静态代理中代理类在编译期就已经确定,而动态代理则是JVM运行时动态生成,静态代理的效率相对动态代理来说相对高一些,但是静态代理代码冗余大,一旦需要修改接口,代理类和委托类都需要修改。

动态代理: 在程序运行时运用反射机制动态创建而成。

Java中的动态代理依靠反射来实现,代理类和委托类不需要实现同一个接口。委托类需要实现接口,否则无法创建动态代理。代理类在JVM运行时动态生成,而不是编译期就能确定。

Java动态代理主要涉及到两个类:java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler。代理类需要实现InvocationHandler接口或者创建匿名内部类,而Proxy用于创建动态动态。

2、代码区别:

静态代理:

  • 接口类。
  • 具体用户管理实现类。
  • 代理类(业务增强类)
  • 客户端调用。
  • 动态代理:(少用户自己实现类)

  • 接口类。
  • 代理类(业务增强类)
  • 客户端调用。
  • 二、静态代理

    1、接口定义要做的事情

    public interface IBuyHouse { // 定义要做的事情 public void buyHouse(); }

    2、具体用户实现类

    /** * 用户实现类(也就是自己做,需要干的事情) */ public class HouseDelegation implements IBuyHouse{ @Override public void buyHouse() { System.out.println("去选房,购房."); } }

    3、代理类(业务增强类)

    /** * 代理类(代替你完成工作,可以附加功能) */ public class HouseAgent implements IBuyHouse{ private IBuyHouse iBuyHouse; public HouseAgent(IBuyHouse iBuyHouse) { this.iBuyHouse = iBuyHouse; } @Override public void buyHouse() { // 1、代替你完成工作 iBuyHouse.buyHouse(); // 2、代理类新增的功能 System.out.println("倒卖你的信息"); } }

    4、测试类

    /** * 测试类 */ public class Test { public static void main(String[] args) { HouseDelegation delegation = new HouseDelegation(); // 1、将你要做的事情,传递给代理对象 HouseAgent agent = new HouseAgent(delegation); // 2、执行代理类方法 agent.buyHouse(); } }

    优点:

    代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合),对于如上的客户端代码,newUserManagerImpl()可以应用工厂将它隐藏,如上只是举个例子而已。

    缺点:

    1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

    2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。如上的代码是只为UserManager类的访问提供了代理,但是如果还要为其他类如Department类提供代理的话,就需要我们再次添加代理Department的代理类。

    通俗点的解释:

    优点:

    1、实现解耦,不需要知道怎么做,只知道代理即可。

    缺点:

    1、大量的重复代码,改代码,需要维护的量大。

    2、每个类都写代码,程序太大时,无法实现。

    三、动态代理

    使用动态代理,我们最大的改变就是不需要定义一个个的代理类了。最重要的是获取到代理对象,有了代理对象,我们就可以直接调用代理对象了。

    1、JDK动态代理类

    JDK动态代理不仅可以代理有接口有实现类的情况,也可以代理只有接口没有实现类的情况。

    使用JDK动态代理无需引入任何外部的jar包,JDK已经给我们提供了一种获取代理对象的API,只需要我们传入相关信息,它就可以返回我们需要的代理对象
    java.lang.reflect.Proxy类的定义如下:

    //CLassLoader loader:类的加载器 //Class<?> interfaces:得到全部的接口(代理的全部接口) //InvocationHandler h:得到InvocationHandler接口的子类的实例(增强业务逻辑的,也就是说增加额外功能) public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException

    java.lang.reflect.InvocationHandler接口的定义如下:

    //Object proxy:被代理的对象 //Method method:要调用的方法 //Object[] args:方法调用时所需要参数 public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }

    1.1、有接口有委托类的情况

    1、接口定义要做的事情

    public interface IBuyHouse { // 定义要做的事情 public void buyHouse(); }

    2、具体用户实现类

    /** * 用户实现类(也就是自己做,需要干的事情) */ public class HouseDelegation implements IBuyHouse{ @Override public void buyHouse() { System.out.println("去选房,购房."); } }

    3、代理类(业务增强类)

    package com.lydms.testPro; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * 功能增强类 */ public class MyProxyPlus implements InvocationHandler { // 把委托对象传递进来进行增强 private Object object; public MyProxyPlus(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 1、执行原来的业务逻辑 Object result = method.invoke(object, args); // 2、执行增强逻辑 System.out.println("对原有的功能进行增强"); return result; // 如果原有业务逻辑有返回值别忘了返回 } }

    4、测试类

    import java.lang.reflect.Proxy; /** * 测试类 */ public class test { public static void main(String[] args) { // 获取IBuyHouse的代理对象 HouseDelegation houseDelegation = new HouseDelegation(); // 1、将你要做的事情,传递给代理对象(并做功能增强MyProxyPlus) IBuyHouse iBuyHouse = (IBuyHouse) Proxy.newProxyInstance(houseDelegation.getClass().getClassLoader(), houseDelegation.getClass().getInterfaces(), new MyProxyPlus(houseDelegation)); // 2、执行代理类方法 iBuyHouse.buyHouse(); } }

    总结:
    同样进行了增强,是不是代理类不见了呢!!!!这就是动态代理的好处,不需要你定义代理类了,你只需要能拿到代理对象就可以

    1.2、仅有接口的情况

     假如说上面我们只定义了IBuyCar接口和IBuyHouse接口,没有委托类(实现类),也是可以玩的。定义一个InvocationHandler接口的实现,用于写业务逻辑,你把所有的业务逻辑写在invoke方法中就行了

    1、接口定义要做的事情

    public interface IBuyHouse { // 定义要做的事情 public void buyHouse(); }

    2、代理类(业务增强类)

    /** * 功能增强类 */ public class MyProxyPlus implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("对原有的功能进行增强"); return null; } }

    3、测试类

    import java.lang.reflect.Proxy; /** * 测试类 */ public class Test { public static void main(String[] args) { // 1、将你要做的事情,传递给代理对象(并做功能增强MyProxyPlus) IBuyHouse iBuyHouse = (IBuyHouse) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{IBuyHouse.class}, new MyProxyPlus()); // 2、执行代理类方法 iBuyHouse.buyHouse(); } }

    总结:

     业务逻辑从无到有不也是一种增强嘛!是不是代理类不见了而且连实现类都不需要了呢!!!!这就是我们Mapper动态代理的底层原理(只要定义接口,不需要写实现类)

    2、CGLIB动态代理

     Java中的动态代理包括JDK动态代理和CGLIB动态代理。使用这两种代理方式我们都可以不用定义代理类,区别在于使用JDK动态代理必须有一个接口类,使用CGLIB动态代理不需要接口类。

     所以如果你要对一个实现了接口的类进行业务增强就用JDK动态代理,如果就对一个普通类进行业务增强就用CGLIB动态代理。如下

    1、cglib是第三方jar,因此需要引入jar包

    <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>

    2、具体用户实现类

    public class Book { public void addBook() { System.out.println("新增图书..."); } }

    3、测试类

    import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class Test { public static void main(String[] args) { Book book = new Book(); // 1、获取book对象的代理对象, Book bookProxy = (Book) Enhancer.create(book.getClass(), new MethodInterceptor() { Object obj = null; // 2、都是对业务逻辑的增强 @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("日志开始........................"); obj = method.invoke(book, objects); System.out.println("日志结束........................"); return obj; } }); // 3、执行方法 bookProxy.addBook(); } }

    结果:

    总结:

    cglib动态代理其实就是把原有对象传进去进行方法拦截,拦截到之后进行逻辑增强

    三、总结

  • 使用代理技术就是为了帮我们在不入侵原有代码的情况下增强业务逻辑。
  • 你完全可以使用静态代理一个一个去定义代理类,但是这样的话太过于繁琐,而且有些情况下你不知道未来会有什么接口(比如咱们的Mybatis,你现在有个UserMapper.java,以后还可能有更多其他的Mapper接口,这些都是不确定的),所以最好采用动态代理生成代理对象吧。
  • 有接口就用JDK动态代理。

    • 你可能想看:

      扫描二维码推送至手机访问。

      版权声明:本文由皇冠云发布,如需转载请注明出处。

      本文链接:https://www.idchg.com/info/24728.html

      分享给朋友:

      “静态代理和动态代理区别(是否有实现类)” 的相关文章

      RackNerd数据中心服务全面解析:选择适合您的VPS解决方案

      大家好,今天我们来聊聊RackNerd,这是一家非常有趣的数据中心服务公司。作为一个提供数据中心解决方案的企业,RackNerd在全球范围内拥有20个数据中心,主要分布在美国、加拿大、英国、荷兰、法国、德国、新加坡和爱尔兰等国。特别的是,RackNerd在美国的布局最为广泛,共有14个数据中心,这不...

      HKT IDC:企业数据中心服务的可靠选择

      HKT IDC服务介绍 HKT IDC是香港电讯专业客服国际有限公司(HKT)旗下的数据中心业务,专注于提供互联网数据中心服务。互联网数据中心,即IDC,简单来说就是一个为各类企业和机构提供托管和租用服务器的专业设施。想象一下,您公司的关键数据和应用都放置在一个高标准的机房环境中,这样不仅能确保数据...

      xTom:灵活可靠的IaaS解决方案,为企业提供优秀网络服务

      xTom是一家成立于2012年的私人控股公司,总部位于德国杜塞尔多夫。它专注于基础设施即服务(IaaS),为各种规模的企业提供可靠的网络和数据中心服务。我对这家公司印象深刻,因为他们提供的解决方案不仅全面,而且非常灵活,能够满足不同客户的需求。 作为一个专业的IaaS提供商,xTom涵盖的服务范围非...

      甲骨文云的永久免费服务:开发者的理想选择

      在现代云计算的环境中,甲骨文云(Oracle Cloud)作为一种强有力的云计算服务,凭借其永久免费服务吸引了许多用户。回想我初次接触甲骨文云时,正是被它提供的多种Always Free服务所吸引,比如我可以免费使用2个实例和20GB的存储空间。这让我在学习和开发上有了更加广阔的可能性,不用担心一开...

      国内到东京快还是首尔快网络速度对比分析

      引言 在这个数字化快速发展的时代,网络速度对我们生活的影响越来越显著。很多时候,我们的工作、学习和娱乐都离不开稳定的网络连接。尤其是当我们考虑访问国外网站或进行国际交流时,网络速度的重要性更是无法忽视。今天,我想带大家探讨国内到东京和首尔的网络速度比较,看看这两个城市的网络表现究竟有何不同。 为什么...

      提升国际数据传输质量的9929线路分析与应用

      谈到9929线路,首先让我给大家介绍一下AS9929线路的基本情况。这条线路是中国联通为了满足国际市场的需求而推出的一种IP传输服务专线。它的起点在香港,通过海底光缆将中国与亚太及北美地区紧密连接。同时,这条线路还在欧洲和非洲设立了多个重要的网络节点(POP点),这就为跨国数据传输提供了坚实的基础。...