【JAVA SE】代理模式(二)--JAVA动态代理

动态代理与静态代理的比较

和静态代理一样,动态代理同样有三种角色:1.抽象角色(用于被代理类、被代理类共同实现的接口);2.被代理角色(被代理的类,是我们最终要引用的对象);3.代理角色(实现共同接口,代理被代理类完成工作,而且可以做一些额外的工作)。

动态代理的抽象角色和被代理角色与静态代理完全相通,而动态代理的代理类是动态实现的。

那么如何动态生成代理类呢?我们只需要实现InvovationHandler接口。

动态代理实现步骤

1.创建一个实现了InocationHandler接口的类,它必须实现invoke方法,去完成被代理类的调用方法。

2.创建被代理类,及被代理类所实现的接口。

3.通过Proxy.newProxyInstanse()方法动态创建一个代理类。

4.调用代理对象实现被代理类的方法。

动态代理代码演示与分析

首先还是要写一个抽象角色的接口,和静态代理不同的(静态代理的抽象角色可以是接口也可以是抽象类)是这里只能用接口,原因后面会说到。

public interface Subject {

        public  void request();

}

然后是被代理角色,与静态代理的被代理角色可以说是完全一样

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject request ");
    }
}

关键的是代理角色动态生成,与静态代理的实现方式有很大区别,需要继承invocationhandler接口,invocationhandler是

java.lang.reflect包下的接口。

public class DynamicSubject implements InvocationHandler{

    private Object  sub;//被代理对象

    public DynamicSubject(Object obj){//构造方法用于传入被代理对象
        this.sub=obj;
    }
    //实现invocationhandler接口,必须实现的方法,被代理对象的业务逻辑也在这里实现
    @Override
    public Object invoke(Object sub, Method method, Object[] args) throws Throwable {
        System.out.println("before method");
        method.invoke(sub,args);//实现被代理对象的业务方法
        System.out.println("after method");
        return null;
    }
}

  之前说静态代理的时候说过,在代理对象中有被代理对象的引用,这里被代理对象因为不知道具体是什么对象所以传入一个Object对象,这样无论被代理对象是什么类型的都可以被这个代理类所代理,也就实现了所谓的动态。

   invoke方法是实现了被代理对象业务逻辑的方法,通过反射调用被代理类的方法(这里如果不清楚反射需要去查查资料,不然不好理解)。method.invoke(sub,args)表示被代理类被执行的方法,sub表示该method方法属于哪个类,args参数列表最总确定了唯一的方法(其实还是反射的内容)。invoke()方法的sub参数 和method参数是通过底层传递过来的。

代理实现:

public class Client {

    public static void main(String[] args) {
        RealSubject realSubject=new RealSubject();//真实对象
        InvocationHandler invocationHandler=new DynamicSubject(realSubject);//获取最终实际完成业务逻辑handler
        Class<?> classType=invocationHandler.getClass();
        //生成代理对象
        Subject subject= (Subject) Proxy.newProxyInstance(classType.getClassLoader(),
        realSubject.getClass().getInterfaces(),invocationHandler);
        subject.request();//调用方法

    }
}
Proxy.newProxyInstance()方法解析

通过Proxy.newProxyInstance方法动态获取一个代理类。该方法有三个参数:1.ClassLoader loader;2.Class<?> interfaces;

3.InvocationHandler h  。下面逐个分析三个参数的作用:

1.ClassLoader loader 动态代理,那么代理类肯定是运行时动态生成的,既然要动态生成肯定需要在运行时将生成的类加载到内存中,那么必然需要一个类加载器ClassLoader (参考JVM 类加载器)

2.Class<?> interfaces 便是该代理类实现的接口数组,实现了哪些接口也就代理了哪些类(代理类和被代理类需要实现共同的接口,这里传入的是RealSubject实现的接口的Class数组,也就是说最终生成的代理类代理了realSubject)。这里也实现了所谓的动态,因为你想让代理类代理谁那么就传入哪个接口。

3.InvocationHandler h 代理类本身是不实现业务逻辑的,业务逻辑交由实现编写好的handler执行。

代理类实现被代理类方法

 subject.request();//调用方法   这句代码等价与RealSubject的request()方法。通过代理类调用request()方法,最终实现了被代理类RealSubject的request 方法。例子中RealSubject只有一个无参的request方法,如果有其他的方法,比如:request(String name),response(),也可以 通过代理类通过反射去调用(invocationHandler中的这句代码通过反射,method.invoke(sub,args),根据不同的方法名,调   用方法的对象,方法参数列表最终确定唯一的被调用方法),也就实现了所谓的动态。 
 
如何实现了动态

 被代理对象RealSubject可以在运行时动态改变,调用的方法(可以随意选择被代理对象的任何方法)可以在运行时动态改变,被   代理对象可以运行时动态改变,因此实现了非常灵活的动态代理。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值