美文网首页
设计模式-代理模式

设计模式-代理模式

作者: snail_fei | 来源:发表于2020-10-29 11:01 被阅读0次

    代理模式:为对象提供一种代理来控制对象的访问。


    代理模式分为静态代理动态代理两种

    • 静态代理:
      • 优点:通过代理类可以对目标类进行扩展;
      • 缺点:每个代理类需要实现委托对象的接口,如果接口增加方法,就需要修改代理类;其次,每一个代理类对应一个委托对象,如果委托对象比较多的话,代理类就非常臃肿;

    静态代理的实现:

    /**
     * 被代理接口定义
     */
    public interface Person {
    
        /**
         * 交作业
         */
        void giveTask();
    }
    
    /**
     * 目标对象
     */
    public class Student implements Person {
    
        private String name;
    
        public Student(String name) {
            this.name = name;
        }
    
        @Override
        public void giveTask() {
            System.out.println(String.format("%s交语文作业", name));
        }
    }
    
    /**
     * 代理类
     */
    public class StudentsProxy implements Person {
    
        Student stu;
    
        public StudentsProxy(Student stu) {
            // 只代理学生对象
            if (stu.getClass() == Student.class) {
                this.stu = stu;
            }
            this.stu = stu;
        }
    
        //代理交作业,调用被代理学生的交作业的行为
        @Override
        public void giveTask() {
            stu.giveTask();
        }
    }
    
    /**
         * 静态代理测试
         */
        @Test
        public void staticProxy() {
            //被代理的学生林浅,他的作业上交有代理对象monitor完成
            Student linqian = new Student("林浅");
    
            //生成代理对象,并将林浅传给代理对象
            Person monitor = new StudentsProxy(linqian);
    
            //班长代理交作业
            monitor.giveTask();
        }
    
    • 动态代理:代理类需要实现InvocationHandler接口,重写invoke方法;
      • JDK动态代理:利用基于反射和拦截器实现;并且要求代理对象必须实现接口
      • CGLIB动态代理:利用ASM开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。主要是对指定的类生成一个子类,覆盖其中的方法,进行增强;但是因为采用的继承,对于final类的方法,是无法继承的;CGLIB采用了fastclass原理,是将方法进行编号,通过编号找到方法避免了通过反射调用。

    动态代理代码的实现:

    /**
     * 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,
     * 当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke方法来进行调用。
     */
    public class StuInvocationHandler<T> implements InvocationHandler {
    
        //invocationHandler持有的被代理对象
        T target;
    
        public StuInvocationHandler(T target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("代理执行" + method.getName() + "方法");
            return method.invoke(target, args);
        }
    }
    
    /**
     * @description 动态代理类
     */
    public class JdkFuDao implements InvocationHandler {
    
        private IPerson target;
    
        public IPerson getInstance(IPerson target) {
            this.target = target;
            Class<?> clazz = target.getClass();
            return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("开始挑选老师");
            Object result = method.invoke(this.target, args);
            System.out.println("双方同意,开始辅导");
            return result;
        }
    }
    
    /**
     * @description 目标对象一定要实现接口,否则不能用动态代理
     */
    public class ZhaoLiu implements IPerson {
        @Override
        public void findTeacher() {
            System.out.println("符合赵柳的要求");
        }
    }
    
      /**
       * 动态代理测试
       */
        @Test
        public void testZhaoLiu() {
            JdkFuDao jdkFuDao = new JdkFuDao();
            // 获取代理对象
            IPerson zhaoLiu = jdkFuDao.getInstance(new ZhaoLiu());
            zhaoLiu.findTeacher();
        }
    

    相关文章

      网友评论

          本文标题:设计模式-代理模式

          本文链接:https://www.haomeiwen.com/subject/gglcvktx.html