热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用代码分别实现jdk动态代理和cglib动态代理_代理模式

代理模式分为静态代理和动态代理,其中动态代理又分为JDK动态代理和CGLIB动态代理代理模式的三个要素:A、抽象的类或者接口——完成一件怎样的事情B、被
97911c01022e91cf2c4702fa3dc92ebe.png

代理模式分为静态代理动态代理,其中动态代理又分为JDK动态代理CGLIB动态代理

代理模式的三个要素:

A、抽象的类或者接口 —— 完成一件怎样的事情

B、被代理对象 —— 事情操作具体内容

C、代理对象 —— 帮助我们完成事情的同时还可以增加其他的功能

为了便于理解写了个具体的例子: 我们找中介租房子

A、抽象的类或者接口 —— 租房子

B、被代理对象 —— 房东

C、代理对象 —— 中介

代理模式的好处:

A、房东可以安心的做自己的事情 —— (被代理对象可以做自己的事情,不会被其他代码所干扰)

B、我们有了问题直接找中介 —— (被代理对象变得比较安全)

C、可以增强代码的扩展性


静态代理

静态代理实现代码:

1、定义抽象的类或者接口 —— 定义我们需要完成租房的事情

package com.bj.proxy1;
/** 抽象的类或者接口* 定义我们需要完成租房的事情*/
public interface LetRoom {public void zf();
}

2、定义被代理对象 —— 房东

package com.bj.proxy1;/** 被代理对象 —— 房东1*/
public class Landlord implements LetRoom{@Overridepublic void zf() {System.out.println("--出租国际大厦1号楼4层406--");}}package com.bj.proxy1;/** 被代理对象 —— 房东2*/
public class Landlord2 implements LetRoom{@Overridepublic void zf() {System.out.println("--出租国际大厦2号楼5层505--");}}

3、定义代理对象 —— 中介

package com.bj.proxy1;/** 代理对象 —— 中介*/
public class Intermediary implements LetRoom{private int money;public Intermediary(int money) {this.money &#61; money;}&#64;Overridepublic void zf() {System.out.println("--收取推荐费50元--");//出租房东的租房——中介调用的租房方法仍然是房东的租房方法if(money <&#61;800 ) {Landlord landlord &#61; new Landlord();landlord.zf();}else if(money <2000 && money >800) {Landlord2 landlord2 &#61; new Landlord2();landlord2.zf();}System.out.println("--收取管理费100元--");}}

4、我们的租房操作

package com.bj.proxy1;//我们的租房操作
public class MyRentRoom {public static void main(String[] args) {Intermediary intermediary &#61; new Intermediary(1000);intermediary.zf();}
}

804da1337dd6b1bd9edec50e12c4c8a0.png
运行结果

现在可以看到&#xff0c;代理模式可以在不修改被代理对象的基础上&#xff0c;通过扩展代理类&#xff0c;进行一些功能的附加与增强。值得注意的是&#xff0c;代理类和被代理类应该共同实现一个接口&#xff0c;或者是共同继承某个类。

静态代理模式缺点&#xff1a;随着被代理对象的增多&#xff0c;我们发现代理对象的压力越来越大&#xff0c;而且里面书写的代码也是比较臃肿的

上面介绍的是静态代理的内容&#xff0c;为什么叫做静态呢&#xff1f;因为它的类型是事先预定好的&#xff0c;比如上面代码中的 Intermediary这个类。下面要介绍的内容就是动态代理。

JDK动态代理

使用步骤

1、 新建一个接口

2、 为接口创建一个实现类

3、 创建代理类实现java.lang.reflect.InvocationHandler接口&#xff0c;重写invoke方法

4、 测试

JDK动态代理实现代码

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//在这个类中书写动态产生代理对象的方法
public class MyInv implements InvocationHandler{private LetRoom lr;public void setLr(LetRoom lr) {this.lr &#61; lr;}//执行该方法就会动态产生代理对象public Object getProxy() {/*** 参数一&#xff1a;保证类型是ClassLoader* 参数二&#xff1a;接口的class数组* 参数三&#xff1a;参数类型是InvocationHandler即可*/Object o &#61; Proxy.newProxyInstance(MyInv.class.getClassLoader(), new Class[]{LetRoom.class}, this);return o;//返回中介}//这个方法就类似与书写中介中的zf()方法&#64;Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {/** proxy:代理对象——中介* method:代理对象中的方法* args&#xff1a;参数--null*/System.out.println("--收取推荐费100元--");//调用了指定房东的zf()方法Object invoke &#61; method.invoke(lr, args);System.out.println("--收取管理费200元--");return invoke;}
}

测试类

public class Test {public static void main(String[] args) {MyInv my &#61; new MyInv();//设置具体的房东my.setLr(new Landlord2());//产生中介代理对象LetRoom proxy &#61; (LetRoom) my.getProxy();proxy.zf(); }
}

d927214ebd457152417865314c38efd1.png
测试结果

结构示意图&#xff1a;

2d41d85869c2937cebea3c5328ee601a.png
结果示意图

JDK代理模式缺点&#xff1a;

我们发现JDK代理模式是必须需要有接口的操作&#xff0c;如果没有对应的接口&#xff0c;这个时候JDK代理就没有办法使用

CGLIB动态代理

通过“继承”可以继承父类所有的公开方法&#xff0c;然后可以重写这些方法&#xff0c;在重写时对这些方法增强&#xff0c;这就是CGLIB的思想。

使用步骤

1、 创建一个实现类

2、导入所需的包

a53bb94436906c674ad637c25a437c93.png

3、 创建代理类实现net.sf.cglib.proxy.MethodInterceptor接口&#xff0c;重写intercept方法

4、 测试

CGLIB动态代理代码实现

import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;public class MethodInv implements MethodInterceptor{//产生代理类对象public Object getProxy() {Enhancer en &#61; new Enhancer();//类似于之前的接口en.setSuperclass(Landlord.class);en.setCallback(this);//是整个设置的内容生效Object o &#61; en.create();return o;}&#64;Overridepublic Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {/*** object:被代理对象* method:被代理对象的方法* objects:参数* methodProxy&#xff1a;代理对象中方法*/System.out.println("--收取推荐费100元--");//调用真正房东的zf()方法Object o1 &#61; methodProxy.invokeSuper(object, objects);System.out.println("--收取管理费200元--");return o1;}}

测试类&#xff1a;

public class Test {public static void main(String[] args) {MethodInv m &#61; new MethodInv();Landlord proxy &#61; (Landlord) m.getProxy();proxy.zf();}
}

1e02a03438dd599641a77b2b492ff9ed.png
测试结果

JDK与Cglib动态代理对比&#xff1f;

1、JDK动态代理只能代理实现了接口的类&#xff0c;没有实现接口的类不能实现JDK的动态代理&#xff1b;

2、Cglib动态代理是针对类实现代理的&#xff0c;运行时动态生成被代理类的子类拦截父类方法调用&#xff0c;因此不能代理声明为final类型的类和方法&#xff1b;

动态代理和静态代理的区别&#xff1f;

1、静态代理在代理前就知道要代理的是哪个对象&#xff0c;而动态代理是运行时才知道&#xff1b;

2、静态代理一般只能代理一个类&#xff0c;而动态代理能代理实现了接口的多个类&#xff1b;

Spring如何选择两种代理模式的&#xff1f;

1、如果目标对象实现了接口&#xff0c;则默认采用JDK动态代理&#xff1b;

2、如果目标对象没有实现接口&#xff0c;则使用Cglib代理&#xff1b;

3、如果目标对象实现了接口&#xff0c;但强制使用了Cglib&#xff0c;则使用Cglib进行代理

原文链接&#xff1a;jdk动态代理和cglib动态代理详解_分享传递价值-CSDN博客_jdk 或 cglib 代理



推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
author-avatar
谢冬彬_868
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有