java设计模式学习笔记4 代理模式-动态代理

因为静态代理模式有一些缺点,所以有了动态代理。

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

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

Object 

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

实际使用的时候,第一个参数obj一般是指代理类的实例 ,method指的是被代理的方法,就像在静态代理中得那个request方法。args指的是参数数组。

2、Proxy: 也就是动态代理类,作用类似于静态代理案例中得ProxySubject

里面最重要的方法是:

static Object 

 newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 

返回的是一个代理类的实例,返回后的代理代理类,可以当做被代理类使用,即可以使用被代理类在Subject接口中声明过的方法。

所谓动态代理,Dynamic Proxy是一种在运行的时候生成的class,生成他的时候必须提供一组interface给他,可以把返回的这个类当做这些接口中的任意接口的实例来使用(多肽)

而代理终归是代理,他不会代替你做实际的工作,所以生成他的时候必须提供一个handler,即InvocationHandler,由他来接管实际工作。

所以在使用动态代理的时候,必须实现InvocationHandler接口,而就不用实现抽象角色Subject接口了。

一、还是建一个抽象角色,可以用抽象类,也可以用接口,但是动态代理只能用接口。应为创建代理类的时候需要具体角色实现的接口数组Class<?>[] interfaces。

/**
 * Created by charleszhu on 14-2-15.
 * 抽象角色
 */
public interface Subject {

    public void request();

}

二、新建真实角色,实现抽象角色

/**
 * Created by charleszhu on 14-2-15.
 * 真实角色
 */
public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("realSubject invoked!!");
    }
}

三、建一个动态代理类,需要实现invocationHandler接口
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by charleszhu on 14-2-15.
 */
public class DynamicProxy implements InvocationHandler{

    private Object sub; //需要有真实对象的引用,为了匹配所有类型,定义为Object类型,使用时候,通过构造函数传递对应类型

    public DynamicProxy(Object sub) {
        this.sub = sub;
    }

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

        System.out.println("before request");

        Object obj = method.invoke(sub,args);// 调用的就是传递对象的对应方法即,sub对应的方法,是真正的方法调用语句

        System.out.println("after request");

        return obj;
    }
}


四、测试
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * Created by charleszhu on 14-2-15.
 */
public class Client {

    public static void main(String[] args) {

        RealSubject realSubject = new RealSubject();

        InvocationHandler handler = new DynamicProxy(realSubject);//构造函数传递相应对象

        Class<?> classType = handler.getClass();

        // 生成相应代理,因为传递realSubject类实现了Subject接口,生成的是$Proxy0这个类的实例,实现了Subject接口,所以可以转换为Subject的实例
        // 当中realSubject.getClass().getInterfaces()也可以写作 new Class[]{Subject.class}
        Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(),realSubject.getClass().getInterfaces(),handler);

        subject.request();// 执行到此处,流程就会跳转到DynamicProxy类的invoke方法里。传递方法名与方法参数(底层自动完成)

        System.out.println(subject.getClass());

    }

}
输出结果是:
before request
realSubject invoked!!
after request
class com.sun.proxy.$Proxy0

可以看到,subject是动态生成的代理类

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值