动态代理

本文总结摘自刘伟老师的《设计模式》和程杰老师的《大话设计模式》

在看本文动态代理前建议看前一篇代理模式的讲解。

动态代理

动态代理是一种较为高级的代理模式,它的典型应用就是Spring AOP。

在传统的代理模式中,客户端通过ProxySubject调用RealSubject类的request()方法,同时还在代理类中封装了其他方法(如preRequest()和postRequest()),可以处理一些其他问题。如果按照这种方法使用代理模式,那么被代理对象类必须是事先已经存在的,并将其作为代理对象的内部成员属性。如果一个被代理对象必须对应一个代理类角色,这将导致系统中的类的个数急剧增加,因此需要想办法减少系统中类的个数,此外,如何在事先不知道被代理对象的情况下使用代理对象,这都是动态代理需要解决的问题。

java动态代理实现相关类位于java.lang.reflect包,主要涉及两个类:

(1)InvocationHandler接口。它是代理实例的调用处理程序实现的接口,该接口中定义了如下方法:

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

invoke()方法中第一个参数proxy表示代理类,第二个参method表示需要代理的方法,第三个参数args表示代理方法的参数数组。

(2)Proxy类。该类即为动态代理类,该类最常用的方法为:

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

newProxyInstance()方法用于根据传入的接口类型interfaces返回一个动态创建的代理类的实例,方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类实现的接口列表(与被代理类的接口列表一致),第三个参数h表示所指派的调用处理程序类。

下面通过一个简单实例来学习如何使用动态代理模式,现在有两个被代理类分别是RealSubjectA和RealSubjectB,它们对于在抽象主题类中定义的抽象方法request()提供了不同的实现,在不断增加新的代理类的情况下,使得客户端通过一个动态代理类来动态选择所代理的被代理对象,实现类图如下:

实现代码如下:

(1)抽象主题类

public interface AbstractSubject
{
	public void request();
}

(2)被代理类A(真实主题类A)

public class RealSubjectA implements AbstractSubject
{	
	public void request()
	{
		System.out.println("真实主题类A!");
	}
}

(3)被代理类B(真实主题类B)

public class RealSubjectB implements AbstractSubject
{	
	public void request()
	{
		System.out.println("真实主题类B!");
	}
}

(4)动态代理类

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

public class DynamicProxy implements InvocationHandler
{
	private Object obj;
	
	public DynamicProxy(){}
	
	public DynamicProxy(Object obj)
	{
   		this.obj=obj;
   	}
   	//实现invoke()方法,调用在被代理类中定义的方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
		preRequest();
        method.invoke(obj, args);
        postRequest();
        return null;
    }

    public void preRequest(){
    System.out.println("调用之前!");
    }

    public void postRequest(){
    System.out.println("调用之后!");
    }

}

(5)客户端测试类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Client
{
	public static void main(String args[])
	{
	InvocationHandler handler =null;
    AbstractSubject subject=null;
    
    handler=new DynamicProxy(new RealSubjectA());
    subject=(AbstractSubject)Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(), new Class[]{AbstractSubject.class}, handler);
    subject.request();
    
    System.out.println("------------------------------");
    
    handler=new DynamicProxy(new RealSubjectB());
    subject=(AbstractSubject)Proxy.newProxyInstance(AbstractSubject.class.getClassLoader(), new Class[]{AbstractSubject.class}, handler);
    subject.request();
	} 
}

在动态代理模式中,对于多个被代理对象,只需要提供一个动态代理类,在动态代理类中无须维护一个与被代理类的引用,用户可以根据需要自定义新的被代理类,在系统设计和客户端编程实现时也无须关心被代理类,系统灵活性和可扩展性更好。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值