代理类学习

亡梦爱人 提交于 2020-02-10 22:40:00

类对象操作时候在外面加一层代理,加一层壳,比如写日记功能,写在外面不接触具体操作对象,相当于代理对厂家的宣传作用。


下面是JDK动态代理
//makeProxy.javapackage daili;

import com.sun.org.apache.xpath.internal.SourceTree;

import java.lang.reflect.*;
import java.util.Arrays;

/*
这个类生成代理对象
JDK动态代理
   1:Proxy:是所有动态代理的父类,专门用于生成代理类或者生成代理对象
        这里的proxy是 java.lang.reflect
       Class<?>(返回值) getPRoxyClass()方法用于生成对象的Class对象,就是电脑计算机中的class对象,属性就是class
       object(返回值)   newProxyInstance()方法用于生成代理对象的实例
   2:InvocationHandler:完成动态代理的整个过程,这是一个接口,自己写一个类实现它
       里面有一个invoke方法(返回值是object)
 */
public class makeProxy {
    //动态代理 :  目标对象  如何获取代理对象  代理要干什么

    //目标对象
    private caculate cal ;
    //获取代理对象需要执行方法,此时需要new makeProxy,所以直接放到构造方法中,此时的参数就是目标对象
    public makeProxy(caculate cal){
        this.cal = cal;
    }
    //获取代理对象的方法
    public Object getProxy(){
        //代理对象
        Object proxy;

        /*
        第一个参数:ClassLoader对象。类加载器对象
        第二个参数:interfaces :接口们。提供目标对象的所有接口,用于实现代理对象和目标对象实现的是同一个接口。就是在代理对象.之后可以出现目标对象的方法.
        第三个参数:是一个实现InvocationHandler接口的类对象,这里的
         */
        ClassLoader loader = cal.getClass().getClassLoader(); //类加载器
        Class [] interfaces = cal.getClass().getInterfaces();
        //下面这个有三个参数
        proxy = Proxy.newProxyInstance(loader,interfaces,new MyInvocationHandler());
        return proxy;
    }
    class MyInvocationHandler implements InvocationHandler{
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
            /*
                这里的proxy参数和上面的proxy = Proxy.newProxyInstance(loader,interfaces,new MyInvocationHandler());,这句话生成的proxy是一个东西,一般不要动,慎用。
                这里的method是一个正在被调用的方法的对象,就是这个参数是一个对象,该对象能执行的方法就是此时正在被执行的方法,比如add方法
                args是此时正在被调用方法的参数

             */
            //先将正事办了,代理代理的那个目标对象的方法,先把这个执行了
            System.out.println("日记执行开始:"+method.getName()+" "+ Arrays.asList(args));
            Object object = method.invoke(cal,args);//执行caculateImpl里面的+ - * /
            System.out.println("日记执行结束:结果是-->"+object);
            return object;
        }
    }

}

 

tast.javapackage daili;

public class test {
    public static void main(String[] args) {
        caculate cal = new caculateImpl();
        Object obj = new makeProxy(cal).getProxy();

        caculate pro = (caculate) obj;

        System.out.println(pro.add(1, 2));
    }
    /*
        问题1:代理对象目标对象能否互相转化?  不行,两个只有实现的接口一样
        问题2:代理对象执行代理方法,为什么会执行实现InvacationHandler对象中的invoke方法
        System.out.println(pro.getClass().getName());
        此时可以得到该代理对象的类名字是$Proxy0
        此时底层的$Proxy0是这样实现的
       class $Proxy0 extends Proxy implements  caculate{
        //这里的构造方法是将自己定义的MyInvocationHandler对象赋值到父类中的h
        public $Proxy0(InvocationHandler h) {
            super(h);
        }
        //在上面对父类的InvocationHandler h中的h赋值之后,每一次调用代理类的代理方法时候,都会执行下面这样的invoke方法。
        @Override
        public int add(int a, int b) {
            return super.h.invoke(this,对象方法,对象参数); 执行父类中的invoke方法,也就是那个自己写的invoke方法。
        }
    }
     */
}

 

//caculateImpl.java
package daili;

public class caculateImpl implements caculate {
    @Override
    public int add(int a, int b) {
        return a+b;
    }
}

 

//caculate.javapackage daili;

public interface caculate {
    public int add(int a,int b);
}

 

代理模式有两种,基于接口的,基于继承的

基于接口的:代理类和普通类只能代理接口里面的方法,目标对象中声明的新方法,代理对象代理不了

基于继承的:代理继承目标对象,这样在目标对象中自己写的方法也可以代理。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!