java 动态代理(JDK和cglib)

设计模式这东东每次看到就明确可过段时间又不能非常流利的说出来。今天就用具体的比喻和实例来加深自己的理解(小弟水平不高有不正确的地方希望大家能指出来)。

(1)代理这个词生活中有非常多比方在街边卖手机卡、充公交地铁卡的小商店他们都起了代理的作用,java中的代理跟这些小店商的作用是一样的。

再比方我想在淘宝上开个服装店但又没有货源怎么办,这时候我就要跟淘宝上某一卖家联系做他的代理。我跟我的商家都要卖衣服(就好比我们都继承了卖衣服的接口sellClothesInterface),我的商家能够卖他网店上的衣服跟我没的关系(就好比实现了sellClothesInterface接口),我的网店也能够卖代理的衣服(同都也实现了sellClothesInterface接口),这个时候买家从我的网店上买了一件衣服而衣服的发货地址确是我的商家的,买家跟我的商家没有不论什么关系,我就起了代理的作用。

(2)用官方的话:代理模式是经常使用的java设计模式,他的特征是代理类与托付类有相同的接口,代理类主要负责为托付类预处理消息、过滤消息、把消息转发给托付类,以及事后处理消息等。代理类与托付类之间一般会存在关联关系,一个代理类的对象与一个托付类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用托付类的对象的相关方法,来提供特定的服务。

(3)代理分为两种:静态代理动态代理

1、静态代理用代码实现例如以下:

public interface SellClothesInterface {
// 都能卖衣服的接口
public void sell();
}
public class BossSellClothes implements SellClothesInterface {
// 我的商家有卖衣服的方法
public void sell() {
System.out.println("确定信息并发货...");
} }
public class MySellClothes implements SellClothesInterface {
private BossSellClothes bossSellClothes; // 构造方法
public MySellClothes(BossSellClothes bossSellClothes) {
this.bossSellClothes = bossSellClothes;
} public void sell() {
// 卖衣服之前先与买家做沟通确定下单
System.out.println("确认信息。确定下单...");
bossSellClothes.sell();
// 买家收货并打款
System.out.println("买家收到货交易结束...");
} }
@org.junit.Test
public void run1() {
BossSellClothes bossSellClothes = new BossSellClothes();// 我的商家实例类
SellClothesInterface scif = new MySellClothes(bossSellClothes);// 我卖衣服类
scif.sell();// 卖衣服
}

执行结果:

确认信息,确定下单...

              确定信息并发货...

              买家收到货交易结束...

从上面代码能够发现每个代理类仅仅能为一个接口服务。所有的代理操作除了调用的方法不一样之外,其它的操作都一样,则此时肯定是反复代码。解决这一问题最好的做法是能够通过一个代理类完毕所有的代理功能,那么此时就必须使用动态代理完毕。

2、动态代理

JDK动态代理中包括一个类和一个接口:

InvocationHandler接口:

       public interface InvocationHandler {

             public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;


       }

參数说明:

Object proxy:指被代理的对象。

Method method:要调用的方法

Object[] args:方法调用时所须要的參数

能够将InvocationHandler接口的子类想象成一个代理的终于操作类,也就是上面静态代理类MySellClothes。

Proxy类:

Proxy类是专门完毕代理的操作类,能够通过此类为一个或多个接口动态地生成实现类,此类提供了例如以下的操作方法:

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


參数说明:

ClassLoader loader:类载入器,用于找到被代理类。

Class<?>[] interfaces:得到所有的接口 。被代理类实现的所有接口。

InvocationHandler h:得到InvocationHandler接口的子类实。

代码修改发下:

/**
* JDK动态代理
*
* @author Administrator
*
*/
public class SellClothesProxy implements InvocationHandler {
private Object target; /**
* 传入被代理类生成代理类
*
* @param target
* @return
*/
public Object buildProxy(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 {
System.out.println("确认信息,确定下单...");
Object result = method.invoke(target, args);
System.out.println("买家收到货交易结束...");
return result;
}
}
	@org.junit.Test
public void run2() {
// 创建代理类并调用方法
SellClothesProxy proxy = new SellClothesProxy();
SellClothesInterface scif = (SellClothesInterface) proxy.buildProxy(new BossSellClothes());
scif.sell();
}

执行结果:

确认信息,确定下单...

      确定信息并发货...

      买家收到货交易结束...

结果出来了,但有一个问题继承InvocationHandler 覆盖invoke方法。那这种方法什么时候被调用的呢?,打个断点发现scif.sell();执行时才调用invoke方法。这个invoke 方法返回一个 Object的实例,然会会强转成你须要的接口。这时候调用你这个接口的方法的时候, 实质上 就是执行了 这个invoke的方法。

(4)cglib动态代理

有了JDK的动态代理再说说cglib。为什么要用cglib呢。JDK的动态代理依靠接口实现,假设有些类并没有实现接口。则不能使用JDK代理,cglib就弥补了这点。cglib是对指定的目标类生成一个子类,并覆盖当中方法实现增强。但既然是类的继承就不能对final修饰的类进行代理了。

public class SellClothesProxy2 implements MethodInterceptor {
private Object target; /**
* 传入被代理类生成代理类
*
* @param target
* @return
*/
public Object buildProxy(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
} @Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("确认信息。确定下单...");
proxy.invokeSuper(obj, args);
System.out.println("买家收到货交易结束...");
return null;
}
}
@org.junit.Test
public void run3() {
SellClothesProxy2 proxy = new SellClothesProxy2();
SellClothesInterface scif = (SellClothesInterface) proxy.buildProxy(new BossSellClothes());
scif.sell();
}

执行结果:

确认信息,确定下单...

      确定信息并发货...

      买家收到货交易结束...

java 代理模式具体解释的更多相关文章

  1. Java代理模式

    java代理模式及动态代理类 1.      代理模式 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目 ...

  2. 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释

    代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...

  3. Java代理模式示例程序

    Java代理模式示例程序 当然不是我想出来的,是我看的一个网上教程里的. 模拟的是一个对电脑公司的代理 真实类的接口: public interface SaleComputer { public S ...

  4. java 代理模式 总结

    1.前言 最近舍友去面试遇到了关于java代理模式的问题. 我虽然知道怎么使用,但是没有做过正经的总结,因此有了这篇随笔,好好总结一下三大代理模式底层原理. 事实上,在开发项目的时候,基本用不上代理, ...

  5. 浅谈java代理模式

    讲解java代理模式 目录 讲解java代理模式 何谓代理模式 静态代理 动态代理 JDK动态代理 CGLIB动态代理 何谓代理模式 代理模式,即Proxy Pattern,23种java常用设计模式 ...

  6. java 代理模式(静态代理、动态代理、Cglib代理) 转载

    Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩 ...

  7. java 代理模式-静态代理与动态代理

    最近在研究SpringAOP,当然要学习AOP就要知道这么健硕.强大的功能的背后究竟隐藏着怎样不可告人的“秘密”?? 接下来就是查阅了许多资料详细的研究了一下Java的代理模式,感觉还是非常非常重要的 ...

  8. Java代理模式/静态代理/动态代理

    代理模式:即Proxy Pattern,常用的设计模式之一.代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问. 代理概念 :为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委 ...

  9. JAVA代理模式与动态代理模式

    1.代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用.代理模式给某 ...

随机推荐

  1. Linux之基础命令——文件操作

    ls(显示指定工作目录下的内容) -a 显示所有文件及目录 包括隐藏文件 -l 除文件名称外,还会将文件类型.权限.拥有者.文件大小等信息详细列出[可以ll简写] -r 将文件以相反次序显示(默认是a ...

  2. java_lock锁

    lock锁是一个接口,jdk5.0新增的接口: 在线程中创建一个他的实现类对象Reentrantlock,默认为fals可以改为true,改为true后是有序的 把操作共享资源的代码放入try中,在t ...

  3. python 2 encode and decode

    https://docs.python.org/2/howto/unicode.html a Unicode string is a sequence of code points, which ar ...

  4. find -print0和xargs -0原理及用法

    平常我们经常把find和xargs搭配使用,例如: find . -name "*.txt" | xargs rm 但是这个命令如果遇到文件名里有空格或者换行符,就会出错.因为xa ...

  5. mysql、MariaDB的简单操作

    mysql的简单操作 一.查看数据库 SHOW DATABASES; 例如: MariaDB [(none)]> show databases; +--------------------+ | ...

  6. jsp include html 乱码问题解决

    方法一: 在被包含的html中,在首行加上 <%@ page language="java" import="java.util.*" pageEncod ...

  7. *** 红包书用法 及 ubuntu全局配置

    使用教程 http://go.wasai.org/sswiki https://home.maysoul.com/wiki/doku.php?id=shadowsocks ubuntu使用教程 htt ...

  8. nodejs的express框架创建https服务器

    一 openssl创建https私钥和证书 1.下载windows版openssl: http://slproweb.com/products/Win32OpenSSL.html Win64OpenS ...

  9. 【codeforces 1109B】Sasha and One More Name

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 如果这个回文串的左半部分,字母全是一样的. 那么显然不可能再分出来了,因为不管怎么分怎么排列,最后肯定都只能和原串一样. 所以无解 其他情况下 ...

  10. POJ-2239 Selecting Courses,三维邻接矩阵实现,钻数据空子。

    Selecting Courses Time Limit: 1000MS   Memory Limit: 65536K       Description It is well known that ...