设计模式-代理/动态代理

最近一段时间在看spring的源码,发现里面大量的使用的代理。代理:就是用代理类实现委托类的一些功能和附加的预处理功能(包括消息过滤,日志等)。代理(proxy)模式:指目标对象给定代理对象,并由代理对象代替真实对象控制客户端对真 实对象的访问, java的代理分为静态代理和动态代理,java 对动态代理有很好的支持,提供了 InvocationHandler接口和 Proxy 类。

1.动态代理和静态代理的区别

静态代理,代理类要实现被代理接口的所有的方法。 
动态代理是利用java反射机制,代理类只需要实现InvocationHandler接口即可,无需实现接口所有方法,在扩展和代码优化上有明显优势。

2.静态代理

我们知道在java中要实现一个类中得功能,有继承父类和实现接口两种方式,也就是根据这一点静态代理可以分为继承代理和接口代理。

2.1继承代理

由于代理的功能一般最好没有实现,否则代理就没有价值了,所以被代理类(委托类)最好是abstract,也就出现了继承代理。

继承代理实现代码

package com.meituan;

/**

* 抽象类

* Created by zsq on 15/5/18.

*/

public abstract class Dao {

public abstract void add();

public abstract void delete();

}

/**

* mysqlao实现Dao

* Created by zsq on 15/5/18.

*/

public class MysqlDao extends Dao{

@Override

public void add() {

System.out.println("insert into mysql datebase!");

}

@Override

public void delete() {

System.out.println("delete from mysql datebase!");

}

}

/**

* oracleDao实现Dao

* Created by zsq on 15/5/18.

*/

public class OracleDao extends Dao {

@Override

public void add() {

System.out.println("insert into oracle datebase!");

}

@Override

public void delete() {

System.out.println("delete from oracle datebase!");

}

}

/**

* Dao的代理类

* Created by zsq on 15/5/18.

*/

public class DaoProxy extends Dao {

private Dao dao;

public DaoProxy(Dao dao) {

this.dao = dao;

}

@Override

public void add() {

dao.add();

}

@Override

public void delete() {

dao.delete();

}

}

/**

* 测试类

* Created by zsq on 15/5/18.

*/

public class DaoTest {

public static void main(String[] args) {

Dao mysqldao=new MysqlDao();

Dao oracledao=new OracleDao();

DaoProxy p=new DaoProxy(mysqldao);

//DaoProxy p=new DaoProxy(oracledao);

p.add();

}

}

输出:insert into mysql datebase!

2.2接口代理

实现方式和继承代理差别不大,只是将abstract换成interface,将extends换成implements

3.动态代理

InvocationHandler 是代理实例的调用处理程序 实现的接口

InvocationHandler


1

2

3

4

5

6

7

package java.lang.reflect;

public interface InvocationHandler {

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

throws Throwable;

}

动态代理是利用java反射机制,代理类通过实现InvocationHandler接口来完成对委托类功能的实现,其实里面是jdk对java的部分代码进行了封装,在实现InvocationHandler接口的时候,需要实现invoke方法,而invoke方法里需要传进2个必要参数代理类和Method,其中method里的invoke方法就可以去实现委托类里所有的接口,因为有了这层封装所以代理类不需要在继承或实现被代理类也可以实现代理功能。

我记得之前看过一个例子,很好的讲述了代理:

公司项目部需要 CEO 签署一个文件,项目负责人会把文件交给 CEO 助理,助理会收文件,等到 CEO 回来后递 CEO,CEO 签署后交给助理,助理收好交给项目负 责人。这个过程中项目负责人其实不知道是否真的是 CEO 签署的文件,有可能是助理打印的 CEO 的签名到文件上。这样助理就是一个代理角色,代替 CEO 处理事务。

代码如下:

动态代理举例
 Collapse source

package com.meituan.proxy;

/**

* 抽象接口

* Created by zsq on 15/5/18.

*/

public interface Leader {

public void sign();

}

/**

* 实现类

* Created by zsq on 15/5/18.

*/

public class CEO implements Leader {

@Override

public void sign() {

System.out.println("CEO 签文件");

}

}

/**

* 动态代理实现类

* Created by zsq on 15/5/18.

*/

public class Assistant implements InvocationHandler {

private Leader leader;

public Assistant(Leader leader) {

this.leader = leader;

}

@Override

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

System.out.println("递给领导");

Object obj = method.invoke(leader, args);

System.out.println("装入袋子,送出");

return obj;

}

}

/**

* 测试类

* Created by zsq on 15/5/18.

*/

public class DynamicTest {

public static void main(String[] args) {

Leader leader = new CEO();

Assistant proxy = new Assistant(leader);

//创建动态代理实例

Leader leader1 = (Leader) Proxy.newProxyInstance(Leader.class.getClassLoader(), new Class[]{Leader.class}, proxy);

leader1.sign();

}

}

输出:

递给领导

CEO 签文件

装入袋子,送出

4.代理的作用

主要用来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情(甚至根本不去执行这个方法),因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象,具体应用的话,比如可以添加调用日志,做事务控制等。

还有一个有趣的作用是可以用作远程调用,比如现在有Java接口,这个接口的实现部署在其它服务器上,在编写客户端代码的时候,没办法直接调用接口方法,因为接口是不能直接生成对象的,这个时候就可以考虑代理模式(动态代理)了,通过Proxy.newProxyInstance代理一个该接口对应的InvocationHandler对象,然后在InvocationHandler的invoke方法内封装通讯细节就可以了。具体的应用,最经典的当然是Java标准库的RMI,比如各种webservice框架中的远程调用,大致都是这么实现的。

其实,我们在不知不觉中就会使用代理了,例如Spring中的AOP,Struts2中的拦截器等。

总结代理的作用:

  1. Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
  2. 动态代理可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
  3. 解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。

时间: 2024-09-29 22:51:03

设计模式-代理/动态代理的相关文章

设计模式之动态代理模式

设计模式之动态代理模式 代理模式: Provide a surrogate or placeholder for another object to controlaccess to it(为其他对象提供一种代理以控制对这个对象的访问).使用代理模式创建代理对象,让代理对象控制目标对象的访问(目标对象可以是远程的对象.创建开销 大的对象或需要安全控制的对象),并且可以在不改变目标对象的情况下添加一些额外的功能. 代理模式相关内容详见本人之前文章:http://www.cnblogs.com/zh

深入解析Java设计模式之动态代理

深入解析Java设计模式之动态代理 代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替"实际"对象的对象.这些操作通常涉及与"实际"对象的通信,因此代理通常充当着中间人的角色,下面是一个用来展示动态代理结构的简单示例: /** 普通(非动态)代理示例: */ interface Interface { void doSomething(); void somethingElse(String arg); } class RealObject

浅谈-Java设计模式之动态代理

动态代理模式(Dynamic Proxy Pattern): 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的. 首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler该接口唯一方法 invoke(Object proxy, Method method, Object[] args) Object

【SSH系列】静态代理&&动态代理

从设计模式说起 代理模式是二十三中设计模式中的一种,代理模式就是指由一个代理主题来操作真实的主题,真实的主题执行具体的业务操作,而代理主题负责其她相关业务,简而言之,代理模式可以由以下三个部分组成: a.抽象角色:通过接口或抽象类声明真实角色实现的业务方法. b.代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作. c.真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用.第一次接触代理模式的是在学习大话设计模式的时候,首先

spring 代理(静态代理&动态代理&cglib代理)

介绍spring AOP之前 先介绍三种常见的代理方式:静态代理,动态代理,cglib代理 代理概述: 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式:即通过代理访问目标对象.这样好处: 可以在目标对象实现的基础上,增强额外的功能操作.(扩展目标对象的功能). 举例:明星(邓紫棋)<------经纪人<-------用户 目标        (代理) 一.静态代理 1)代理的对象要实现与目标对象一样的接口 2)举例:保存用户(模拟) Dao,直接保存 DaoProxy,给保存

代理模式(静态代理+动态代理)——JAVA

代理模式是常用的java设计模式,他的特征是代理类与目标类有同样的接口,代理类主要负责为目标类预处理消息.过滤消息.把消息转发给目标类,以及事后处理消息等.代理类与目标类之间通常会存在关联关系,一个代理类的对象与一个目标类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用目标类的对象的相关方法,来提供特定的服务. 结构图如下: 按照代理的创建时期,代理类可以分为静态代理和动态代理. 静态代理:由程序员创建或特定工具自动生成源代码,再对其编译.在程序运行前,代理类(Proxy)的.clas

Java设计模式—Proxy动态代理模式

代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 图 1. 代理模式 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性.Java 动态代理机制以巧妙的方式近乎完

JAVA设计模式之动态代理

代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性.Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的

设计模式之动态代理(Java的JDK动态代理实现)

对于JDK的动态代理,孔浩老师说学习的方法是把它记下来. 先写一个主题接口类,表示要完成的一个主题. package com.liwei.dynaproxy; /** * 要代理的主题接口 * @author Administrator * */ public interface Subject { public void miai(); } 再写一个实现类,这个实现类实现这个接口.当然,这个实现类就是我们要代理的对象. 为了区别不同的类的对象,我们为Person类增加了一个name属性,并且通

【设计模式】动态代理 &amp;&amp; 模拟JDK动态代理

真正理解动态代理需要明白回答以下问题: 什么叫动态代理?怎么产生? 动态代理的作用?可配置的事务,权限控制,日志等等....只有你想不到,没有动态代理做不到. 下面来回答以上3个问题: 先说下静态代理: 方法:创建代理类,代理类包含被代理对象的方法并在被代理方法的前后加添加的方法. 创建代理类可以用继承接口或者聚合(implements)被代理对象的接口来实现,然后传入被代理对象的实例.其中聚合并继承好,使用继承的时候如果代理类需要嵌套代理类或者创建不同的代理类,需要创建不同的代理类.造成类泛滥