代理模式与动态代理

        代理模式的作用是:为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一

个客户不想或不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

         编程与设计思想:掌握代理模式对于Spring AOP的学习是至关重要的,甚至比Spring AOP

本身的学习还要重要

        代理模式的一般角色:

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

        代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象

        提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行

        真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

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


        静态代理:

        抽象角色:定义了一个真实对象和代理对象的方法

public abstract class Subject {
	public abstract void request();
}
        真实角色:实现了抽象角色中的共同方法

public class RealSubject extends Subject {

	@Override
	public void request() {
		System.out.println("from real subject");
	}

}
        代理角色:
public class ProxySubject extends Subject {
	private Subject realSubject; //持有真实对象的一个引用,通过它可以调用真实对象的方法
	
	public ProxySubject(Subject realSubject) {  //通过构造函数获得真实对象
		this.realSubject = realSubject;
	}
	
	@Override
	public void request() {
		preRequest();              //代理对象添加在真实对象具体操作前的操作
		realSubject.request();     //真实对象的具体操作
		postRequest();             //代理对象添加在真实对象具体操作后的操作
	}
	
	private void preRequest() {  
		System.out.println("pre request");
	}
	
	private void postRequest() {  
		System.out.println("post request");
	}
}
        客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理RealSubject类,

同样达到目的,同时还封装了其他方法(preRequest(),postRequest()),可以处理一些其他问题。

        如果按照上述的方法使用代理模式,那么真实角色必须事先已经存在,并将其作为代理对象的

内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨

胀;此外如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类

解决。


        动态代理类

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

        1、Interface InvocationHandler:该接口中仅定义了一个方法

              public object invoke(Object obj, Method method, Object[] args);

              在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的

              request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

        2、Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容

              1) protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。Proxy类中

                     持有 InvocationHandler接口的一个实例。

             2) static Class getProxyClass(ClassLoader loader, Class[] interfaces)获得一个代理类

                    其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

             3)static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHander h)

                   返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的

                   在Subject 接口中声明过的方法)


        所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它是你必须提供一组

interface给它,然后该类就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface

中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你做实质性的工作,在

生成它的实例时你必须提供一个handler,由它接管实际的工作


        抽象角色和真实角色和上面一样,不再添加。

        代理角色:该代理角色持有真实角色引用,并且可以是任意真实角色,即这一个代理类可以代理

Subject的所有真实角色

public class ProxySubject implements InvocationHandler {
	private Object realSubject;
	
	public ProxySubject(Object realSubject) {
		this.realSubject = realSubject;
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("pre processing");
		method.invoke(realSubject, args);
		System.out.println("post processing");
		return null;
	}
}
        测试类代码:

public class Client {
	public static void main(String[] args) {
		RealSubject subject = new RealSubject();
		
		InvocationHandler ih = new ProxySubject(subject);  //将真实对象实例传给代理对象,那么可以改变这个真实对象
		
		Class<?> clazz = subject.getClass();  //获取真实对象的Class对象
		
		Subject s = (Subject)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), ih);
		s.request();  //调用该方法时,流程转到ih参数的invoke方法,method参数就是s调用的方法名,参数就是s调用的方法的参数
	}
}
        通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject

接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常

灵活的动态代理关系。

        动态代理步骤:

        1、创建一个实现接口InvocationHandler的类,它必须实现invoke方法

        2、创建被代理的类以及接口

        3、通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, 

               InvocationHandler h)创建一个代理。

        4、通过代理调用方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值