在之前的代码调用阶段,我们用action调用service的方法实现业务即可。

由于之前在service中实现的业务可能不能够满足当先客户的要求,需要我们重新修改service中的方法,但是service的方法不只在我们这个模块使用,在其他模块也在调用,其他模块调用的时候,现有的service方法已经能够满足业务需求,所以我们不能只为了我们的业务而修改service,导致其他模块授影响。

那怎么办呢?

可以通过动态代理的方式,扩展我们的service中的方法实现,使得在原油的方法中增加更多的业务,而不是实际修改service中的方法,这种实现技术就叫做动态代理。

动态代理:在不修改原业务的基础上,基于原业务方法,进行重新的扩展,实现新的业务。

例如下面的例子:

1、 旧业务

买家调用action,购买衣服,衣服在数据库的标价为50元,购买流程就是简单的调用。

2、 新业务

在原先的价格上可以使用优惠券,但是这个功能在以前没有实现过,我们通过代理类,代理了原先的接口方法,在这个方法的基础上,修改了返回值。

代理实现流程:

1、 书写代理类和代理方法,在代理方法中实现代理Proxy.newProxyInstance

2、 代理中需要的参数分别为:被代理的类的类加载器soneObjectclass.getClassLoader(),被代理类的所有实现接口new Class[] { Interface.class },句柄方法new InvocationHandler()

3、 在句柄方法中复写invoke方法,invoke方法的输入有3个参数Object proxy(代理类对象), Method method(被代理类的方法),Object[] args(被代理类方法的传入参数),在这个方法中,我们可以定制化的开发新的业务。

4、 获取代理类,强转成被代理的接口

5、 最后,我们可以像没被代理一样,调用接口的认可方法,方法被调用后,方法名和参数列表将被传入代理类的invoke方法中,进行新业务的逻辑流程。

上代码:

IBoss.java

/*** 这是一个业务的接口,这个接口中的业务就是返回衣服的价格* @author wilson**/
public interface IBoss {//接口int yifu(String size);
}

Boss.java

/*** 实现了卖衣服的接口* 自定义了自己的业务,卖裤子* @author wilson**/
public class Boss implements IBoss{public int yifu(String size){System.err.println("天猫小强旗舰店,老板给客户发快递----衣服型号:"+size);//这件衣服的价钱,从数据库读取return 50;}public void kuzi(){System.err.println("天猫小强旗舰店,老板给客户发快递----裤子");}
}

SaleAction.java

public class SaleAction {/*** 不使用代理,直接调用方法* 方法中规定什么业务,就只能调用什么业务,规定什么返回值,就只能输出什么返回值*/@Testpublic void saleByBossSelf() throws Exception {IBoss boss = new Boss();System.out.println("老板自营!");int money = boss.yifu("xxl");// 老板自己卖衣服,不需要客服,结果就是没有聊天记录System.out.println("衣服成交价:" + money);/*程序输出:天猫小强旗舰店,老板给客户发快递----衣服型号:xxl老板自营!衣服成交价:50*/}
}

使用动态代理:

ProxyBoss.java

public class ProxyBoss {/*** 对接口方法进行代理*/@SuppressWarnings("unchecked")//写法一:通过参数传入代理对象的Class ,更灵活,更方便的适配public static <T> T getProxy(final int discountCoupon,final Class<?> interfaceClass, final Class<?> implementsClass)throws Exception {return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class[] { interfaceClass }, new InvocationHandler() {public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {Integer returnValue = (Integer) method.invoke(implementsClass.newInstance(), args);// 调用原始对象以后返回的值return returnValue - discountCoupon;}});}//写法二:在方法内部指定对象的Classpublic static IBoss getProxyBoss(final int discountCoupon) throws Exception {Object proxedObj = Proxy.newProxyInstance(Boss.class.getClassLoader(),new Class[] { IBoss.class }, new InvocationHandler() {public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {Integer returnValue = (Integer) method.invoke(new Boss(),args);// 调用原始对象以后返回的值return returnValue - discountCoupon;}});return (IBoss)proxedObj;}
}

调用动态代理:

ProxySaleAction.java

/*** 什么是动态代理? 简单的写一个模板接口,剩下的个性化工作,好给动态代理来完成!*/
public class ProxySaleAction {/***使用代理,在这个代理中,只代理了Boss的yifu方法*定制化业务,可以改变原接口的参数、返回值等*/@Testpublic void saleByProxy() throws Exception {/**  将代理的方法实例化成接口  10是要打折的价格数*  如下这种写法对应的是ProxyBoss.java中的public static <T> T getProxy(final int...这种方法*  IBoss boss = ProxyBoss.getProxy(10,IBoss.class,Boss.class);*///如下这种写法对应的是ProxyBoss.java中的public static IBoss getProxyBoss(final int 这种方法....IBoss boss = ProxyBoss.getProxyBoss(10);// 将代理的方法实例化成接口System.out.println("代理经营!");//调用接口的方法,实际上调用方式没有变 调用了invoke()方法int money = boss.yifu("xxl");System.out.println("衣服成交价:" + money);/*程序输出:代理经营!衣服成交价:40天猫小强旗舰店,老板给客户发快递----衣服型号:xxl*/}
}

//==================另外一个总结=======================

上代码:

Waiter.java

public interface Waiter {public void server();public String sayHello(String name);}

GirWaiter.java

public class GirlWaiter implements Waiter{@Overridepublic void server() {System.out.println("服务中………………");}@Overridepublic String sayHello(String name) {return "Hello"+name;}
}

ProxyDemo2.java

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;import org.junit.Test;public class ProxyDemo2 {@Testpublic void demo1(){//用当前的java类文件来获得ClassLoader对象.ClassLoader loader = ProxyDemo2.class.getClassLoader();//这是个数组,要用大括号括起来,而且返回的得到的是Class对象.Class[] interfaces = {Waiter.class}; /**loader - 定义代理类的类加载器      interfaces - 代理类要实现的接口列表h - 指派方法调用的调用处理程序newProxyInstance方法中需要传递三个参数:* loader:* interfaces:代理类要实现的接口列表* h:  h - 指派方法调用的调用处理程序* 应付一下:* ClassLoader:* Class[]返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。此方法相当于: Proxy.getProxyClass(loader, interfaces).getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler });想为Waiter接口的一个实现类生成一个代理.就需要传入你这个类的实现接口的class.为什么是一个数组,一个类可以实现多个接口.想生成这个Waiter接口的代理类....传入Waiter.classProxy.newProxyInstance返回的是个Object类型,需要去强转MyInvocationHandler类中没有含有参数的构造方法,所以在new一个MyInvocationHandler的时候 一定要传入一个参数.这样才能编译通过.才能真正new出一个MyInvocationHandler对象. */    Waiter waiter = (Waiter) Proxy.newProxyInstance(loader, interfaces, new MyInvocationHandler(new GirlWaiter()));//调用waiter中的方法就相当域调用invoke的方法.
        waiter.server();String s = waiter.sayHello("张三");System.out.println(s);}
}//InvocationHandler 是代理实例的调用处理程序 实现的接口。
class MyInvocationHandler implements InvocationHandler{/*//在这个MyInvocationHandler的构造方法中传入一个GirlWaiter对象public MyInvocationHandler(GirlWaiter girlWaiter){}*//*对这个接口生成了一个代理类了....到底是生成一个接口的代理类还是生成这个接口的实现类的代理类....两个都可以,但是接口相当于其实现类的父类  但是接口更通用...所以一般都是生成接口的代理类.*/private Waiter waiter;public MyInvocationHandler(Waiter waiter){//传入参数的这个地方也用接口来做,更通用.this.waiter = waiter;}@Override/**不要忘记invoke()方法也是有参数的!!* invoke方法:*     * 调用waiter的某个方法都相当于调用invoke方法.*         * invoke方法的参数:*             * proxy:代理对象.*             * method:正在执行的方法.*             * args:方法的参数列表.*/public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//只想增强一个固定的方法,方法名是固定的,通过if判断进行筛选.../** debug....* demo1中waiter.server() 的时候* method.getName = server ; args = null ; obj = null;* demo1中waiter.sayHello("张三");* method.getName = sayHello ; args = '张三' ; obj = "Hello张三"*/Object obj = null;if("server".equals(method.getName())){System.out.println("微笑");obj = method.invoke(waiter,args);}else{obj = method.invoke(waiter,args);}return obj;}
}

运行输出:

微笑
服务中………………
Hello张三

PS:之间总结的关于静态代理的博文

本文转自SummerChill博客园博客,原文链接:http://www.cnblogs.com/DreamDrive/p/6855599.html,如需转载请自行联系原作者

Java动态代理总结相关推荐

  1. java动态代理【一】

    java动态代理的定义:为其他目标类的方法增加切面的逻辑,即在执行目标类方法的时候,先去执行一段如校验检测的逻辑代码.java通俗一点就是生成一个继承目标类的子类,并在每个调用方法都添加一段逻辑. 应 ...

  2. Java动态代理的实现

    动态代理作为代理模式的一种扩展形式,广泛应用于框架(尤其是基于AOP的框架)的设计与开发,本文将通过实例来讲解Java动态代理的实现过程. 友情提示:本文略有难度,读者需具备代理模式相关基础知识,. ...

  3. Java动态代理与Cglib代理

    为什么80%的码农都做不了架构师?>>>    最近又继续回来死磕Spring源码,以前看的也忘得差不多了,这次先把Spring使用的动态代理cglib看了一下,打好基础知识. cg ...

  4. JAVA 动态代理学习记录

    打算用JAVA实现一个简单的RPC框架,看完RPC参考代码之后,感觉RPC的实现主要用到了两个方面的JAVA知识:网络通信和动态代理.因此,先补补动态代理的知识.---多看看代码中写的注释 参考:Ja ...

  5. 初看Mybatis 源码 (二) Java动态代理类

    先抛出一个问题,用过Mybatis的都知道,我们只需要定义一个Dao的接口,在里面写上一些CRUD相关操作,然后配置一下sql映射文件,就可以达到调用接口中的方法,然后执行sql语句的效果,为什么呢? ...

  6. Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP

    Java初学者如何迈出AOP第一步--使用Java 动态代理实现AOP xBird 原创  (参与分:36,专家分:90)   发表:2004-9-3 上午9:37   版本:1.0   阅读:160 ...

  7. Java动态代理的应用

    先看一下代理模式,这个应该是设计模式中最简单的一个了,类图 代理模式最大的特点就是代理类和实际业务类实现同一个接口(或继承同一父类),代理对象持有一个实际对象的引用,外部调用时操作的是代理对象,而在代 ...

  8. java动态代理上是否能再进行一层代理

    CGLIB动态代理类 import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.p ...

  9. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  10. Java动态代理类使用

    Java动态代理类使用 Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类: 一.Interface InvocationHandler:该接口中仅定义了一个方法O ...

最新文章

  1. 《NoSQL精粹》思维导图读书笔记
  2. 一些基本数据类型的类封装(包装类)
  3. jzoj2137-(GDKOI2004)城市统计【二维前缀和,bfs】
  4. 设计模式_4_适配器模式(AdapterPattern, 多个功能的结合)
  5. 喜欢爱C/C++的人不要浮躁
  6. Streamr助你掌控自己的数据
  7. python写crm_Python CRM项目八
  8. Oracle分析函数之FIRST_VALUE和LAST_VALUE
  9. 【行为识别】基于matlab轨迹法行为识别【含Matlab源码 375期】
  10. python 输入参数有误_Python OpenCV错误:输入参数的大小不匹配
  11. hadoop+hbase安装
  12. 重磅消息,Micrium的uCOS全家桶将推出免费商业授权
  13. 双系统安装 Ubuntu 18.04 以及删除双系统中的 Ubuntu 的方法
  14. jQuery学习笔记(3)之Ajax下
  15. android手机连接hdmi,手机hdmi转接线的介绍以及连接方法
  16. idea 如何将本地新建项目上传到gitlab
  17. 如何实现双向绑定?底层原理是什么?
  18. 一边攒大米,一边做公益
  19. matlab memory 代数环,[2018年最新整理]simulink代数环解决方法.doc
  20. 2019年10月8日股市走势预测

热门文章

  1. vue-router路由管理器的使用
  2. 林元图为什么不创造一部新的武功
  3. 稻船敬二:日本游戏业界大势已去
  4. js,数组合并的方法+数组添加元素的方法
  5. 鸿蒙系统是手机系统还是电脑系统,除手机、平板、电脑外的设备,华为全面启用鸿蒙系统...
  6. 【机器学习笔记2.2】用逻辑回归预测马疝病的死亡率
  7. Windows+VMware虚拟机 虚拟机能ping通主机,主机不能ping通虚拟机
  8. Java面向对象程序设计(第二版)袁绍欣 第十章课后习题答案
  9. Win11的两个实用技巧系列之蓝牙无法连接、错误代码0x80070483怎么办?
  10. 【rtsp client取海康IPC H264视频流】——sdp数据格式