Java代理模式的理解(一)

一 静态代理模式

在静态代理模式中有三类角色,理解了这三类角色也就理解了代理模式:

a.抽象对象:定义了真实角色和抽象角色的公共接口(可以是类,也可以是接口)Subject;

b.代理角色:代理角色内部包含有对真实角色的引用,通过这个引用去执行真实角色想要完成的任务;除此之外,代理角色可以完成其他的一些功能;

c.真实角色:实际要完成任务的角色,是我们始终要引用的对象。

代理角色和真实角色均实现了(或继承了)抽象角色。

写一段代码来举例:

 

//抽象角色,定义公共部分
interface Subject { 
    public void request();
}

//真实角色
class RealSubject implements Subject {
    public void request() {
        do something;
   } 
}

//抽象角色,内部保存真实角色的引用
class ProxySubject implements Subject {
    private RealSubject sub;
    
    public ProxySubject(RealSubject obj) {
        this.sub = obj;//获得真实角色的实例引用
    }

   public void request() {
       sub.request();//通过真实角色的引用去执行最终要完成的任务
  }
}

public static void main(String[] args) {
		Subject proxy = new ProxySubject();
		proxy.request();
}

 

 

二 动态代理模式

在学习动态代理模式时,学完了整个过程,我还是没有理解,下面的描述是我从自己理解的角度出发的,也许不适合别人阅读,也许会产生共鸣。

动态代理模式也是代理模式,所以它也会有三种角色。

   抽象角色,定义公共部分,interface Subject;

   真实角色,完成实际的工作,class RealSubject implements Subject。

 

  class DynamicSubject:里面保存真实角色的引用,实现了InvocationHandler接口,InvocationHandler接口中有一个invoke方法,接受三个参数:

             一个是代理实例;

              一个是要执行方法的Method对象,通过调用Method对象的invoke()方法,便可以执行该方法了;

              一个是执行该方法所需要的参数。

 

 在使用动态代理模式时,首先需要得到真实角色的一个实例:RealSubject real = new RealSubject();

DynamicSubject实现了InvocationHandler接口,DynamicSubject里保存了一个真实角色的引用sub,通过构造方法来得到它:InvocationHandler handler = new DyanmicSubject(real);

 

接下来就是通过Proxy动态的生成一个动态代理类(也就是代理模式中的代理角色),分析一下,如果要生一个代理类需要哪些条件?根据静态代理来分析:

 (1)要实现Subject接口,谁实现了Subject接口?RealSubject!所以需要RealSubject实现的接口的列表:RealSubject.class.getInterfaces()。

 (2)要实现Subject中的方法。但是动态代理把执行方法的任务交给了InvocationHandler,所以需要一个InvocationHandler的对象。

Proxy动态生成了该代理类后,返回一个该类的实例。想一想,代理模式的前提是什么?是有一个定义了公共部分的接口Subject,由Subject的一个实例去调用要执行的方法。生成的动态代理类实现了哪个接口?Subject!所以返回的该动态代理类的实例必定是Subject类型的:

   Subject sub = (Subject)动态代理类实例;

   sub.调用要执行的方法;

回想一下:动态代理模式把执行方法的任务交给了InvocationHandler,所以sub.调用要执行的方法这一步实际上是把执行动作转移到了handler上了,调用了handler的invoke方法。handler的invoke方法再去调用实际要执行方法的Method对象的invoke()方法。

 

以上的描述可能比较乱,总结一下:

 (1)动态代理模式,也需要三种角色:抽象角色Subject;真实角色RealSubject;代理角色,由Proxy动态生成。

(2)动态代理模式把执行方法的任务交给了InvocationHandler,所以需要一个类去实现InvocationHandler接口,并且实现invoke方法。

 (3)生成动态代理类需要三个条件:类加载器;真实角色实现的接口列表;handler。需要handler的原因是因为:方法最终是在handler的invoke()方法中执行;在生成动态代理类的实例时,完成代理类和handler的关联。

//抽象角色
public interface Subject {
   public void request();
}

//真实角色
public class RealSubject implements Subject {

	@Override
	public void request() {
		System.out.println("From real Subject");

	}

}

//InvocationHandler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/*
 * 该代理类内部的属性是Object类型,实际使用的时候通过构造方法传递进来一个对象sub
 * 此外,该类还实现了invoke方法,该方法中的method.invoke其实就是调用被代理对象将要执行的方法,
 * 方法参数是sub,表示该方法从属于sub
 * 
 */
public class DynamicSubject implements InvocationHandler {
	
	private Object sub;
	
	public DynamicSubject(Object obj) {
		this.sub = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("before : " + method);
		System.out.println("method name : " + method.getName() + "," + args);
		method.invoke(sub, args); 
		System.out.println("after : " + method);	
		
		return null;
	}

}


public class Client {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		RealSubject realSubject = new RealSubject();
		InvocationHandler handler = new DynamicSubject(realSubject);
		
		Class<?> clazz = handler.getClass();
		
		//下面的代码一次性生成代理
		//完成两件事:动态生成一个代理类,并且生成这个类的一个实例
		Subject subject = (Subject) Proxy.newProxyInstance(clazz.getClassLoader(),
				RealSubject.class.getInterfaces(), handler);
		
		subject.request();//实际上将是将方法的执行转移到了handler上了,调用handler.invoke()方法
		System.out.println(subject.getClass());
	}

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值