静态代理和动态模式

原创 2012年03月23日 10:16:28

案例场景:

1、一个售票站点,可以代买火车票,当我们需要买火车票的时候,我们可以自己去火车站买,也可以找售票点买火车票,在这里,我们可以把售票点视为代理类。从程序的角度上讲,我们就相当与一个对象,如果每个人都自己去火车站买票,那么要实现这个功能的话,相当与在每个对象中都要写上一个买票的方法,况且买票前后可能要做一些相关的操作,例如排队等候,退票等等,这样实现的程序代码重用性很高,所以我们可以把这些公共的事交给代理类去做,我们只要想买票,那就交给代理类,让代理类帮我们办好,我们最后只需要取票即可,所有的人都可以找这个代理类。

2、在日常生活中,我们可能有这样的需求,实现吃饭-工作-睡觉,但是我们的主体可能是工作,例如我们定义一个工作的实现类workImpl,里面有个工作的方法doWork,但是工作前我们得吃饭,工作后我们得睡觉,这些我们不能直接定义在workImpl中,因为它只能处理工作的方法,纯面向对象的思想只允许将类的相关属性和方法写在一个类中,因此按照这个思想,面向对象是不能帮我们解决的,因此这里我们可以使用面向切面编程,把吃饭和睡觉这些方法交给代理类去做,在这里相当与一个切面。


代理模式涉及到的角色:

抽象角色:声明真实对象和代理对象共同的接口

代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其它的操作,相当与对真实对象进行封装。

真实角色:代理角色所代表的真实对象,使我们最终要引用的对象。


下面,我们用代码来描述上面的场景2:

抽象角色:声明真实对象和代理对象共同的接口

public interface Work {
	public void doWork();

}
代理角色

package cn.com.test1;
//ProxyWork这里被认为是一个切面了,不再是个类,因此它可以有吃饭、睡觉等各种方法。
public class ProxyWork implements Work {
	private WorkImpl workImpl;//真实对象的引用
	
	public Proxy(){
		workImpl=new WorkImpl();
	}
	
	public void doWork(){
		eat();//工作前吃饭
		workImpl.doWork();
		sleep();//工作后睡觉
		
	}


        //附加其它操作
public void eat(){System.out.println("吃饭");}
public void sleep(){System.out.println("睡觉");}}


真实角色:使我们最终要引用的对象。

package cn.com.test1;

public class WorkImpl implements Work {

	public void doWork() {
		System.out.println("工作");

	}
}


测试类:

public static void main(String[] args) {
		Work work=new ProxyWork();
		work.doWork();
}

输出结果:吃饭  工作  睡觉
当我们调用工作方法的时候,代理类帮我们把吃饭和睡觉都做好了,就是说当我们要执行某个业务逻辑的时候,在执行前或执行后都要执行的方法,我们可以交给代理类去做,让代理类帮我们实现。


动态代理:

使用上面代理模式的弊端:在ProxyWork代理类中,只能处理工作,也就是说只能完成吃饭-工作-睡觉,我们有时候会有很多中间方法,比如说吃饭-运动-睡觉,吃饭-玩游戏-睡觉...,也就是中间方法很多,上面只能处理工作,不灵活,这时候我们可以使用动态代理;

Java动态代理类位于java.lang.reflect包下,一般主要涉及以下两个类:

(1)Interface InvocationHandler:该接口中只定义了一个方法

  public Object invoke(Object obj,Method method,Object[ ] args);在实际使用时,第一个参数obj一般是指代理类,method是指被代理的方法,例如上面的work,args表示方法参数数组,这个抽象方法在代理类中动态实现。

编写上面的动态代理类:

package cn.com.test1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//定义动态代理类
public class DynaProxy implements InvocationHandler {
	private Object obj;//真实对象
	public DynaProxy(Object obj){
		this.obj=obj;
		
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		eat();
		//执行真实对象中的方法(方法所在的对象,方法接收的参数数组)
		Object o=method.invoke(obj, args);
		sleep();
		return o;
	}
	
	public void eat(){
		System.out.println("吃饭");
	}

	public void sleep(){
		System.out.println("睡觉");
	}
}


(2)Proxy:该类即为动态代理类,主要包括:protected  Proxy(InvocationHandler h):构造函数,用于给内部的h赋值

static Class getProxyClass(ClassLoader loader,Class[ ] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的接口数组

static Object newProxyInstance(ClassLoader loader,Class[ ] interfaces,InvocationHandler h),返回代理类的一个实例,返回后的代理类可以当作被代理类使用。

编写上面的测试类:

public static void main(String[] args) {
		// 声明一个真实对象
		Work work = new WorkImpl();
		// 声明一个能AOP执行的真实对象方法中的对象
		DynaProxy dynaProxy = new DynaProxy(work);
		// 产生代理对象,相当与上面的ProxyWork
		//newProxyInstance(真实对象使用的类加载器,要代理的类的接口,Aop执行的方法)
		Object obj = Proxy.newProxyInstance(work.getClass.getClassLoader(),
				work.getClass.getClassInterfaces(), dynaProxy);
		Work w=(Work)obj;
		w.doWork();
		
}

这样,我们的动态代理类就实现了,所谓Dynamic Proxy是这样一种类:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。Spring中的AOP实现原理即为动态代理类。




相关文章推荐

java中的静态和动态代理模式

一.  简介 代理模式(Proxy Pattern)是23种Java常用设计模式之一。 代理模式的定义:Provide a surrogate or placeholder for another 用...

java设计模式之代理模式 (静态&动态)

为其他对象提供一个代理控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。 代理类和委托类要实现相同的接口,因为代理真正实现的还是委托类的方...

Java代理模式(静态模式&动态模式简介)

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 意图:为其他对象提供一种代理...
  • glrh123
  • glrh123
  • 2016年07月15日 18:17
  • 122

JAVA 设计模式:静态代理VS动态代理

采用Java代理模式,代理类通过调用委托类对象的方法,来提供特定的服务。委托类需要实现一个业务接口,代理类返回委托类的实例接口对象。 按照代理类的创建时期,可以分为:静态代理和动态代理。 ...

Java设计模式学习06——静态代理与动态代理

一、代理模式为某个对象提供一个代理,从而控制这个代理的访问。代理类和委托类具有共同的父类或父接口,这样在任何使用委托类对象的地方都可以使用代理类对象替代。代理类负责请求的预处理、过滤、将请求分配给委托...
  • xu__cg
  • xu__cg
  • 2016年10月30日 09:57
  • 1181

Java设计模式之—静态代理和动态代理

代理从字面意思来看就是,替代XX去做某事,在我们的程序中,一般替代实际对象去进行操作,扮演着中间人的角色: 客户端 –> 业务类 客户端 –> 代理 –>业务类(代理) 代理接口int...
  • jeffleo
  • jeffleo
  • 2016年08月17日 00:08
  • 419

设计模式之静态代理&动态代理

我们先看一个这样的场景:

java设计模式之静态代理与动态代理

1.静态代理类: 由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。 由此可见,代理类可以...

黑马程序员:Java基础总结----静态代理模式&动态代理

黑马程序员:Java基础总结 静态代理模式&动态代理  ASP.Net+Android+IO开发、.Net培训、期待与您交流! ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:静态代理和动态模式
举报原因:
原因补充:

(最多只允许输入30个字)