前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >静态代理和动态代理区别(是否有实现类)

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

作者头像
ha_lydms
发布于 2023-08-09 13:13:49
发布于 2023-08-09 13:13:49
23500
代码可运行
举报
文章被收录于专栏:学习内容学习内容
运行总次数:0
代码可运行

一、简介

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

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

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

1、代理分类:

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

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

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

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

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

2、代码区别:

静态代理:

  1. 接口类。
  2. 具体用户管理实现类。
  3. 代理类(业务增强类)
  4. 客户端调用。

动态代理:(少用户自己实现类)

  1. 接口类。
  2. 代理类(业务增强类)
  3. 客户端调用。

二、静态代理

1、接口定义要做的事情
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface IBuyHouse {

//    定义要做的事情
    public void buyHouse();
}
2、具体用户实现类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 用户实现类(也就是自己做,需要干的事情)
 */
public class HouseDelegation implements IBuyHouse{

    @Override
    public void buyHouse() {
        System.out.println("去选房,购房.");
    }
}
3、代理类(业务增强类)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 代理类(代替你完成工作,可以附加功能)
 */
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、测试类
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 测试类
 */
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类的定义如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//CLassLoader loader:类的加载器  
//Class<?> interfaces:得到全部的接口(代理的全部接口)
//InvocationHandler h:得到InvocationHandler接口的子类的实例(增强业务逻辑的,也就是说增加额外功能)
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException  

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Object proxy:被代理的对象  
//Method method:要调用的方法  
//Object[] args:方法调用时所需要参数  
public interface InvocationHandler {  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;  
}  
1.1、有接口有委托类的情况

1、接口定义要做的事情

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface IBuyHouse {

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

2、具体用户实现类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 用户实现类(也就是自己做,需要干的事情)
 */
public class HouseDelegation implements IBuyHouse{

    @Override
    public void buyHouse() {
        System.out.println("去选房,购房.");
    }
}

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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、测试类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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、接口定义要做的事情

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface IBuyHouse {

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 功能增强类
 */
public class MyProxyPlus implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("对原有的功能进行增强");
        return null;
    }
}

3、测试类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

2、具体用户实现类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Book {  
    public void addBook() {  
        System.out.println("新增图书...");  
    }  
}  

3、测试类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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动态代理其实就是把原有对象传进去进行方法拦截,拦截到之后进行逻辑增强

三、总结

  1. 使用代理技术就是为了帮我们在不入侵原有代码的情况下增强业务逻辑。
  2. 你完全可以使用静态代理一个一个去定义代理类,但是这样的话太过于繁琐,而且有些情况下你不知道未来会有什么接口(比如咱们的Mybatis,你现在有个UserMapper.java,以后还可能有更多其他的Mapper接口,这些都是不确定的),所以最好采用动态代理生成代理对象吧。
  3. 有接口就用JDK动态代理。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
第06天 静态代理和动态代理
代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象 (real object) 的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。
程序员Leo
2023/08/16
1800
第06天 静态代理和动态代理
java 代理模式-静态代理与动态代理
    举个例子吧:我们生活中的租房问题。假如我们去租个房子,我们大多数情况下是不会知道房主(就是真正租房,一手货源)的,我们是不是都是先去某些租房平台,或者去找当地的中介去询问何时的房子。我们通过九牛二虎之力在中介那里找到了个物美价廉的房子后,你的租金是不是交给了中介,中介还会收取一些额外的推荐费啦,押金啦、手续费等之类的,那么好,这样的一小段,就已经出来了其中两大核心对象了。
Arebirth
2019/09/24
4050
java 代理模式-静态代理与动态代理
静态代理和动态代理详解[通俗易懂]
代理模式是指:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。
全栈程序员站长
2022/11/07
6290
静态代理和动态代理详解[通俗易懂]
静态代理与动态代理
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/52025353
DannyHoo
2018/09/13
3390
静态代理与动态代理
java动态代理和静态代理的实现
代理模式:为其他对象提供一种代理以控制目标对象的访问,在某些情况下, 一个对象不适合或者不能直接引用另外一个对象,代理对象可以在这个客户类和目标对象中起到一个桥梁作用。
IT云清
2019/01/22
4280
Java 静态代理、Java动态代理、CGLIB动态代理
Java 的代理就是客户类不再直接和委托类打交道, 而是通过一个中间层来访问, 这个中间层就是代理。为啥要这样呢, 是因为使用代理有 2 个优势:
java思维导图
2019/05/21
7.1K0
jdk动态代理和cglb动态代理
静态代理是在编译时就确定了代理类的代码,在程序运行前就已经存在了代理类的class文件。代理类与委托类的关系在编译时就已经确定,因此被称为静态代理。在静态代理中,代理类需要实现与委托类相同的接口或者继承委托类的父类,以便能够对委托类进行代理操作。
一个风轻云淡
2023/10/15
2140
jdk动态代理和cglb动态代理
太好了!总算有人把动态代理、CGlib、AOP都说清楚了!
静态代理是代理类在编译期间就创建好了,不是编译器生成的代理类,而是手动创建的类。在编译时就已经将接口,被代理类,代理类等确定下来。,软件设计中所指的代理一般是指静态代理,也就是在代码中显式指定的代理。
Bug开发工程师
2019/07/12
45.1K3
jdk动态代理和cglib动态代理详解
如上图,代理模式可分为动态代理和静态代理,我们比较常用的有动态代理中的jdk动态代理和Cglib代理,像spring框架、hibernate框架中都采用了JDK动态代理,下面将结合代码阐述两种代理模式的使用与区别。
全栈程序员站长
2022/08/29
7040
jdk动态代理和cglib动态代理详解
Java 动态代理详解
动态代理在Java中有着广泛的应用,比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。
小旋锋
2019/01/21
1.1K0
浅谈 Java 动态代理
Proxy Pattern是程序设计中的一种设计模式,又称委托模式。代理对象对真实对象提供一种代理以控制其他对象对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理对象具备真实对象的功能,并代替真实对象完成相应操作,并能够在操作执行的前后,对操作进行增强处理。、
ph0ebus
2023/05/16
2830
浅谈 Java 动态代理
动态代理机制
代理模式是指,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。 换句话说,使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。 客户类真正想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象。客户类对目标对象的访问是通过访问代理对象来实现的。代理类与目标类要实现同一个接口。 例如:有A,B,C三个类,A原来可以调用C类的方法,现在因为某种原因C类不允许A类调用其方法,但B类可以调用C类的方法,A类通过B类调用C类的方法。这里B是C的代理,A通过代理B访问C。 原来的访问关系:
技术交流
2022/11/18
2380
动态代理机制
代理、静态、动态
为其他对象提供一种代理以控制这个对象的访问,在某些情况下一个对象不能直接访问那个对象时,代理就起到了客户端和被代理对象 (委托类) 中介作用。
张小驰出没
2021/12/06
2300
代理、静态、动态
JDK动态代理和CGLIB动态代理
Java动态代理是一种在运行时创建代理对象的技术,它允许开发者在不修改目标类代码的情况下,通过代理类对目标类的实例方法进行增强或拦截。动态代理的核心价值在于能够在程序运行阶段动态地生成一个实现了预定义接口的新类,这个新类就是所谓的“代理类”。
程序猿川子
2025/02/27
1420
JDK动态代理和CGLIB动态代理
Java动态代理一览笔录
1、什么是代理? 比较经典的含义如销售代理,签订合同的基础上,为委托人(厂商)销售某些特定产品或全部产品的代理商,对价格、条款及其他交易条件可全权处理。我们从销售代理那里购买产品,通常是不知道销售代理背后的委托人(厂商)是谁,也就是 "委托人" 对于我们来说是不可见的。 代理,简单来说,也就是提供代理人,并有代理人全权处理委托人的事务。 在Java中,代理模式,类似的,也就是为某个对象(即委托人)提供一个代理对象(即代理人),并由代理对象(即代理人)全权控制对于原对象(即委托人)的访问。客户对于委托人不再可
斯武丶风晴
2018/03/01
7190
Java动态代理一览笔录
jdk的动态代理机制_jdk动态代理
摘要:   代理模式为其他对象提供了一种代理以控制对这个对象的访问,具体实现包括两大类:静态代理和动态代理。Java动态代理机制的出现使得Java开发人员只需要简单地指定一组接口及委托类对象便能动态地获得代理类,并且其所生成的代理类在将所有的方法调用分派到委托对象上反射执行的同时,还可以对方法进行增强,这也正是Spring AOP的实现基础。通过阅读本文,读者将会对代理模式和Java动态代理机制有更加深入的理解。
全栈程序员站长
2022/11/03
4540
jdk的动态代理机制_jdk动态代理
探索Java动态代理的奥秘:JDK vs CGLIB
动态代理是一种在 运行时动态生成代理类 的技术,无需手动编写代理类代码。它通过拦截目标方法的调用,实现对核心逻辑的 无侵入式增强(如日志、事务、权限控制等)。
用户7954602
2025/02/04
1180
探索Java动态代理的奥秘:JDK vs CGLIB
JAVA中的静态代理、动态代理以及CGLIB动态代理分析
静态代理其实就是在程序运行之前,提前写好被代理方法的代理类,编译后运行。在程序运行之前,class已经存在。 下面我们实现一个静态代理demo:
冬天里的懒猫
2020/08/03
3750
Spring AOP基础之代理模式.静态代理和动态代理
一、代理模式介绍 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。 简言之,代理模式就是设置一个中间代理来控制访问原目标对象,以达到增强原对象的功能和简化访问方式。
用户9184480
2024/12/13
1520
Spring AOP基础之代理模式.静态代理和动态代理
动态代理详解
代理模式是23种设计模式之一。设计模式是前人总结的,在软件开发过程遇到常用问题的解决方案,常见的设计模式有单例模式、工厂模式、适配器模式等等。
会洗碗的CV工程师
2023/11/10
1830
动态代理详解
相关推荐
第06天 静态代理和动态代理
更多 >
LV.1
这个人很懒,什么都没有留下~
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文