理解Java动态代理(1)—找我还钱?我出钱要你的命

代理模式是最常用的一个设计模式之一,理解起来也是很简单,一张图足以说明了,LZ就不废话了。

至于代理模式能干嘛也不是LZ今天想说的,今天主要想简单介绍下JAVA里面的动态代理。“动”当然是相对“静”来说的,那么什么是静,怎么就又动了呢?LZ想举个生活中常见的例子来说明,俗话说“谈钱伤感情”,但生活所迫LZ曾经可没少找人借个一百两百五的,话说借钱一时爽,还钱……(请自行造句),好点的心平气和的委婉的说,横点的就拳脚相加啊。我们来用接口表示下借钱者这个角色,他们可以采取peace或force的方式找我还钱:


/**
* 借钱方
*
* @author moon
*
*/
public interface ILender {
/**和平方式*/
public long peace(String name);

/**暴力方式*/
public long force(String name);
}

我月中找张三借钱:


public class ZhangSanImpl implements ILender {

public long peace(String name) {
System.out.println("心平气和的找" + name + "要账。");
return 100;
}

public long force(String name) {
System.out.println("以暴力方式找" + name + "要账");
return 250;
}

}

月底又找李四借钱(都是好欺负的货,动手干不过我):


public class LiSiImpl implements ILender {

public long peace(String name) {
System.out.println("心平气和的找" + name + "要账。");
return 100;
}

public long force(String name) {
System.out.println("以暴力方式找" + name + "要账");
return 250;
}
}

张三和李四发现我老是借钱又拖帐,于是就合伙找了年级里一个比较横的角色(外号"JDK",由来是因为我叫jd,他是jd
killer)来代他们要帐,好说不行就动手。看这就是代理模式。


/**
* 借钱者的代理人
*
* @author jdzhan
*
*/
public class CommonLenderProxy implements ILender {

/** 委托者 */
private ILender delegator;

public CommonLenderProxy(ILender delegator) {
this.delegator = delegator;
}

public long peace(String name) {
return delegator.peace(name);
}

public long force(String name) {
System.out.println("开始工作");
// 执行方法
long result = delegator.force(name);
System.out.println("搞定收工");
return result;
}

}

于是乎我屈于淫威或者武力只能乖乖还钱鸟:

 // Common Proxy
CommonLenderProxy proxy = new CommonLenderProxy(new ZhangSanImpl());
long money = proxy.force("zhanjindong");
System.out.println("要回了" + money + "块QB");

开始工作
以暴力方式找zhanjindong要账
搞定收工
要回了250块QB

Ok,上面我用了亲身的一个小栗子说明了静态代理,那动态代理到底怎么实现,又有什么好处呢?我们先直接把上面的实现给出来。JDK动态代理中包含一个接口和一个类:

InvocationHandler接口:

public interface InvocationHandler {
  public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}

Proxy类:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException

"JDK"觉得代人要钱很有钱途,于是搞了个“帮会”:


/**
* “JDK”代人人要账帮会
*
* @author jdzhan
*
*/
public class DynamicLenderProxy implements InvocationHandler {
private Object target;

/**
* 绑定委托对象并返回一个代理类
*
* @param target
* @return
*/
public Object bind(Object target) {
this.target = target;
// 取得代理对象
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}

/**
* 调用方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.getName().equals("force")) {
Object result = null;
System.out.println("开始工作");
// 执行方法
result = method.invoke(target, args);
System.out.println("工作结束");
return result;
} else {
return method.invoke(target, args);
}

}

}

是不是感觉比之前牛X多了,当然目的还是找人要账,可能是我也可能是马六:

 //JDK Dynamic Proxy
DynamicLenderProxy proxy = new DynamicLenderProxy();
ILender bookProxy = (ILender) proxy.bind(new LiSiImpl());
long money = bookProxy.force("maliu");
System.out.println("要回了" + money + "块QB");

心平气和的找maliu要账。
要回了100块QB

我们通常还可以把动态代理跟注解结合起来用,“帮会”越来越大,想立稳得提供多种业务,比如暴力要账,可以让人选择用什么样的暴力,是赤手空拳还是刀墙棍棒伺候:


import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Force {

String weapon() default "拳头";

}

有了这个注解可以在接口里使用:


/**
* 借钱方
*
* @author moon
*
*/
public interface ILender {
/**和平方式*/
public long peace(String name);

/**暴力方式*/
@Force(weapon = "AK47")
public long force(String name);
}

改下DynamicLenderProxy里的invoke方法:


/**
* 调用方法
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

if (method.isAnnotationPresent(Force.class)) {
Force force = method.getAnnotation(Force.class);
String weapon =
force.weapon();
System.out.println("用" + weapon + "开始工作");
Object result = method.invoke(target, args);
System.out.println("搞定收工");
return result;

} else {
return method.invoke(target, args);
}
}

拿AK47找人要钱谁敢不还:

用AK47开始工作
以暴力方式找zhanjindong要账
搞定收工
要回了250块QB

(这里有个问题注解只能用在接口里,用在实现类里如何获取到呢?)

JDK动态代理的使用就是这么简单,下面就说为什么叫动态代理了。假设有一天我为实在还不了钱了,于是就想花钱找人把借钱给我的人干掉,于是我成了个凶手:

public interface IMurderer {

@Force(weapon = "沙漠之音")
public long kill(String name);
}


public class JdzhanImpl implements IMurderer {

public void kill(String name) {
System.out.println("找我还钱?我要你" + name + "的命");
}

}

恰好这时"JDK"拓展了业务,也干杀手这一行当了,于是乎当初找我还钱的人成了我雇的杀手,但是实现一点没动:

  DynamicLenderProxy2 proxy = new DynamicLenderProxy2();
IMurderer murderer = (IMurderer) proxy.bind(new JdzhanImpl());
murderer.kill("LiSi");

用沙漠之音开始工作
找我还钱?我要你LiSi的命
搞定收工

好了,这个我胡扯的例子说完了,动态代理的好处也就体现出来了:

可以为不同的接口进行代理

如果我们用静态代理的话那么每个接口我们都得写一个代理类。

但是竟然动态为什么不更灵活点呢,JDK的动态代理还是需依赖接口的,接口就像一个契约或收据,你找我还钱最起码得有欠条吧,下篇文章介绍下Cglib动态代理,就是怎么在没有收据的情况下找人还钱。

理解Java动态代理(1)—找我还钱?我出钱要你的命,布布扣,bubuko.com

时间: 2024-08-10 00:03:58

理解Java动态代理(1)—找我还钱?我出钱要你的命的相关文章

深入理解 Java 动态代理机制

Java 有两种代理方式,一种是静态代理,另一种是动态代理.对于静态代理,其实就是通过依赖注入,对对象进行封装,不让外部知道实现的细节.很多 API 就是通过这种形式来封装的. 代理模式结构图(图片来自<大话设计模式>) 下面看下两者在概念上的解释: 静态代理 静态代理类:由程序员创建或者由第三方工具生成,再进行编译:在程序运行之前,代理类的.class文件已经存在了. 静态代理类通常只代理一个类. 静态代理事先知道要代理的是什么. 动态代理 动态代理类:在程序运行时,通过反射机制动态生成.

理解java动态代理

java动态代理是java语言的一项高级特性.在平时的项目开发中,可能很难遇到动态代理的案例.但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP.今天我们就聊一聊java动态代理的实现原理. jdk对于动态代理的支持主要依赖于两个类:Proxy和InvocationHandler.我们先看一下类图. Subject类是主题类,定义了我要做什么.我们需要代理的类即实现Subject接口的RealSubject. 1.InvocationHandler InvocationHand

深入理解java动态代理的实现机制

今天将从以下5方面来系统的学习一下java动态代理的实现机制: 什么是代理 什么是静态代理 什么是动态代理 动态代理的实现机制 动态代理的使用场景 1,什么是代理 相信大家都有购买过火车票或者机票的经历,有的人在携程买,有的在飞猪,也有的在微信上买等等,这里的携程飞猪微信也好都是受铁路部的委托代理售卖火车票,这里的携程飞猪就是代理类,铁路部就是委托类,这就是代理 2,什么是静态代理 所谓的静态代理就是在代码运行之前,代理类就已经存在,通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生

彻底理解JAVA动态代理

注:本文转自 http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html 代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Subject { public void doSomething(); } public class RealSubject i

Java动态代理的理解

代理可分为两类: 静态代理和动态代理 1.静态代理: /*定义一个业务接口*/ public interface Count { // 查看账户方法 public void queryCount(); // 修改账户方法 public void updateCount(); } /*定义一个委托类,实现该业务接口*/ public class CountImpl implements Count { @Override public void queryCount() { System.out.

Java 动态代理机制分析及扩展,第 1 部分

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅读本文,读者将会对 Java 动态代理机制有更加深入的理解.本文首先从 Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现. 回页首 代理:设计模式 代理是一种常用的设计

Java 动态代理机制分析及扩展

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅读本文,读者将会对 Java 动态代理机制有更加深入的理解.本文首先从 Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现. 代理:设计模式 代理是一种常用的设计模式,其

java高级----&gt;Java动态代理的原理

Java动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.下面我们开始动态代理的学习. 目录导航   动态代理的简要说明 简单的Java代理 Java的动态代理 Java动态代理的原理 友情链接 动态代理的简要说明 在java的动态代理机制中,有两个重要的类或接口,一个是 In

[转]Java 动态代理机制分析及扩展

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅读本文,读者将会对 Java 动态代理机制有更加深入的理解.本文首先从 Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现. 代理:设计模式 代理是一种常用的设计模式,其