千家信息网

Java三种代理模式的简单介绍

发表于:2025-11-09 作者:千家信息网编辑
千家信息网最后更新 2025年11月09日,本篇内容主要讲解"Java三种代理模式的简单介绍",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java三种代理模式的简单介绍"吧!目录一、代理模式是什么二
千家信息网最后更新 2025年11月09日Java三种代理模式的简单介绍

本篇内容主要讲解"Java三种代理模式的简单介绍",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java三种代理模式的简单介绍"吧!

目录
  • 一、代理模式是什么

  • 二、Java的三种代理模式

    • 1.静态代理

    • 2.动态代理(也叫JDK代理)

    • 3.Cglib代理

一、代理模式是什么

代理模式是一种设计模式,简单说即是在不改变源码的情况下,实现对目标对象的功能扩展。

比如有个歌手对象叫Singer,这个对象有一个唱歌方法叫sing()。

1 public class Singer{2     public void sing(){3         System.out.println("唱一首歌");4     }  5 }

假如你希望,通过你的某种方式生产出来的歌手对象,在唱歌前后还要想观众问好和答谢,也即对目标对象Singer的sing方法进行功能扩展

1 public void sing(){2     System.out.println("向观众问好");3     System.out.println("唱一首歌");4     System.out.println("谢谢大家");5 }

但是往往你又不能直接对源代码进行修改,可能是你希望原来的对象还保持原来的样子,又或许你提供的只是一个可插拔的插件,甚至你有可能都不知道你要对哪个目标对象进行扩展。这时就需要用到java的代理模式了。网上好多用生活中的经理人的例子来解释"代理",看似通俗易懂,但我觉得不适合程序员去理解。程序员应该从代码的本质入手。

二、Java的三种代理模式

想要实现以上的需求有三种方式,这一部分我们只看三种模式的代码怎么写,先不涉及实现原理的部分。

1.静态代理

 1 public interface ISinger { 2     void sing(); 3 } 4  5 /** 6  *  目标对象实现了某一接口 7  */ 8 public class Singer implements ISinger{ 9     public void sing(){10         System.out.println("唱一首歌");11     }  12 }13 14 /**15  *  代理对象和目标对象实现相同的接口16  */17 public class SingerProxy implements ISinger{18     // 接收目标对象,以便调用sing方法19     private ISinger target;20     public UserDaoProxy(ISinger target){21         this.target=target;22     }23     // 对目标对象的sing方法进行功能扩展24     public void sing() {25         System.out.println("向观众问好");26         target.sing();27         System.out.println("谢谢大家");28     }29 }

测试

 1 /** 2  * 测试类 3  */ 4 public class Test { 5     public static void main(String[] args) { 6         //目标对象 7         ISinger target = new Singer(); 8         //代理对象 9         ISinger proxy = new SingerProxy(target);10         //执行的是代理的方法11         proxy.sing();12     }13 }

  总结:其实这里做的事情无非就是,创建一个代理类SingerProxy,继承了ISinger接口并实现了其中的方法。只不过这种实现特意包含了目标对象的方法,正是这种特征使得看起来像是"扩展"了目标对象的方法。假使代理对象中只是简单地对sing方法做了另一种实现而没有包含目标对象的方法,也就不能算作代理模式了。所以这里的包含是关键。

  缺点:这种实现方式很直观也很简单,但其缺点是代理对象必须提前写出,如果接口层发生了变化,代理对象的代码也要进行维护。如果能在运行时动态地写出代理对象,不但减少了一大批代理类的代码,也少了不断维护的烦恼,不过运行时的效率必定受到影响。这种方式就是接下来的动态代理。

2.动态代理(也叫JDK代理)

跟静态代理的前提一样,依然是对Singer对象进行扩展

 1 public interface ISinger { 2     void sing(); 3 } 4  5 /** 6  *  目标对象实现了某一接口 7  */ 8 public class Singer implements ISinger{ 9     public void sing(){10         System.out.println("唱一首歌");11     }  12 }

这回直接上测试,由于java底层封装了实现细节(之后会详细讲),所以代码非常简单,格式也基本上固定。

调用Proxy类的静态方法newProxyInstance即可,该方法会返回代理类对象

static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h )
接收的三个参数依次为:

  • ClassLoader loader:指定当前目标对象使用类加载器,写法固定

  • Class[] interfaces:目标对象实现的接口的类型,写法固定

  • InvocationHandler h:事件处理接口,需传入一个实现类,一般直接使用匿名内部类

测试代码

 1 public class Test{ 2     public static void main(String[] args) { 3   Singer target = new Singer(); 4         ISinger proxy  = (ISinger) Proxy.newProxyInstance( 5                 target.getClass().getClassLoader(), 6                 target.getClass().getInterfaces(), 7                 new InvocationHandler() { 8                     @Override 9                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {10                         System.out.println("向观众问好");11                         //执行目标对象方法12                         Object returnValue = method.invoke(target, args);13                         System.out.println("谢谢大家");14                         return returnValue;15                     }16                 });17         proxy.sing();18     }19 }

总结:以上代码只有标黄的部分是需要自己写出,其余部分全都是固定代码。由于java封装了newProxyInstance这个方法的实现细节,所以使用起来才能这么方便,具体的底层原理将会在下一小节说明。

缺点:可以看出静态代理和JDK代理有一个共同的缺点,就是目标对象必须实现一个或多个接口,加入没有,则可以使用Cglib代理。

3.Cglib代理

前提条件:

  • 需要引入cglib的jar文件,由于Spring的核心包中已经包括了Cglib功能,所以也可以直接引入spring-core-3.2.5.jar

  • 目标类不能为final

  • 目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法

1 /**2  * 目标对象,没有实现任何接口3  */4 public class Singer{5 6     public void sing() {7         System.out.println("唱一首歌");8     }9 }
 1 /** 2  * Cglib子类代理工厂 3  */ 4 public class ProxyFactory implements MethodInterceptor{ 5     // 维护目标对象 6     private Object target; 7  8     public ProxyFactory(Object target) { 9         this.target = target;10     }11 12     // 给目标对象创建一个代理对象13     public Object getProxyInstance(){14         //1.工具类15         Enhancer en = new Enhancer();16         //2.设置父类17         en.setSuperclass(target.getClass());18         //3.设置回调函数19         en.setCallback(this);20         //4.创建子类(代理对象)21         return en.create();22     }23 24     @Override25     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {26         System.out.println("向观众问好");27         //执行目标对象的方法28         Object returnValue = method.invoke(target, args);29         System.out.println("谢谢大家");30         return returnValue;31     }32 }

这里的代码也非常固定,只有标黄部分是需要自己写出

测试

 1 /** 2  * 测试类 3  */ 4 public class Test{ 5     public static void main(String[] args){ 6         //目标对象 7         Singer target = new Singer(); 8         //代理对象 9         Singer proxy = (Singer)new ProxyFactory(target).getProxyInstance();10         //执行代理对象的方法11         proxy.sing();12     }13 }

总结:三种代理模式各有优缺点和相应的适用范围,主要看目标对象是否实现了接口。以Spring框架所选择的代理模式举例

  • 在Spring的AOP编程中:

  • 如果加入容器的目标对象有实现接口,用JDK代理

  • 如果目标对象没有实现接口,用Cglib代理

到此,相信大家对"Java三种代理模式的简单介绍"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

代理 对象 目标 方法 模式 接口 代码 测试 观众 静态 一首 功能 动态 方式 缺点 部分 就是 内容 写法 前提 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 北京每每度网络技术有限公司 土木转行建筑结构软件开发怎么样 omap平台软件开发 未来互联网大会领先科技 江苏直销网络技术价目表 梦幻手游长安城服务器怎么样 天天生鲜项目 数据库 电脑页面提示内部服务器错误 汕头网络技术 金山区品牌软件开发代理价格 持续集成等于敏捷软件开发 安信交易服务器慢 怎么减少数据库主从的同步延迟 为什么天谕手游服务器不一样 数据库软件企业获亿元战略融资 学校宿舍系统软件开发 2021年春秋杯网络安全联赛秋季赛 服务器谁来买 本地账户安全账户数据库 福建信息化软件开发单价 联想集团深腾服务器cpu 龙谷游戏是服务器吗 误删除数据库表结构 翻墙服务器哪些可以用 链式数据库的代表 云流媒体服务器怎么接入监控系统 京昆高速哪个服务器可以掉头 湖北项目软件开发哪家正规 政府购买软件开发服务合同 大数据与软件开发哪个前景好
0