• 代理模式


    一 代理模式简介

    代理(Proxy)是一种设计模式 提供了对目标对象另外的访问方式

    代理对象代理目标对象 达到增强目标对象功能的目的

    二 静态代理

    需要定义接口或者父类 代理对象与目标对象一起实现相同接口或者继承相同父类

    优点: 在不修改目标对象的功能前提下 对目标功能扩展

    缺点: 因为代理对象需要与目标对象一起实现相同接口或者继承相同父类 所以会有很多代理类 导致类太多 同时 如果接口增加方法 代理对象与目标对象都要维护

    1. 接口

    /**
     * 接口
     * Created by Hy on 2020/7/10.
     */
    public interface IUserService {
    
        void insertUser();
    
        String deleteUser(int id);
    }

    2. 目标对象

    /**
     * 目标对象
     * Created by Hy on 2020/7/10.
     */
    public class UserService implements IUserService {
    
        @Override
        public void insertUser() {
            System.out.println("insert ok");
        }
    
        @Override
        public String deleteUser(int id) {
            System.out.println("delete... ... ...");
            return "id = " + id + " delete ok";
        }
    }

    3. 代理对象

    /**
     * 代理对象
     * Created by Hy on 2020/7/13.
     */
    public class UserServiceProxy implements IUserService {
    
        private IUserService target; //目标对象
    
        public UserServiceProxy(IUserService target) {
            this.target = target;
        }
    
        @Override
        public void insertUser() {
            System.out.println("增强方法体 1/2");
            target.insertUser();
            System.out.println("增强方法体 2/2");
        }
    
        @Override
        public String deleteUser(int id) {
            id++; //增强参数
            String s = target.deleteUser(id);
            s = s + "!!!"; //增强返回值
            return s;
        }
    }

    4. 测试

    @Test
    public void test01() {
        // 创建目标对象
        UserService target = new UserService();
        // 创建代理对象
        UserServiceProxy proxy = new UserServiceProxy(target);
        // 使用代理对象调用方法
        proxy.insertUser();
        String s = proxy.deleteUser(1);
        System.out.println(s);
    }

    三 动态代理(接口代理)

    需要定义接口让目标对象实现 使用java.lang.reflect.Proxy动态的在内存中构建代理对象

    优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象不需要实现接口

    缺点: 目标对象一定要实现接口 否则不能用动态代理

    1. 接口

    /**
     * 接口
     * Created by Hy on 2020/7/10.
     */
    public interface IUserService {
    
        void insertUser();
    
        String deleteUser(int id);
    }

    2. 目标对象

    /**
     * 目标对象
     * Created by Hy on 2020/7/10.
     */
    public class UserService implements IUserService {
    
        @Override
        public void insertUser() {
            System.out.println("insert ok");
        }
    
        @Override
        public String deleteUser(int id) {
            System.out.println("delete... ... ...");
            return "id = " + id + " delete ok";
        }
    }

    3. 代理工厂

    /**
     * 代理工厂
     * Created by Hy on 2020/7/13.
     */
    public class ProxyFactory {
    
        private Object target; //目标对象
    
        public ProxyFactory(Object target) {
            this.target = target;
        }
    
        public Object createProxyInstance() {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
                /**
                 * 代理对象调用的所有方法都会触发该方法执行
                 * @param proxy 代理对象
                 * @param method 被代理的方法
                 * @param args 被代理的方法传参
                 * @return 被代理的方法返回值
                 * @throws Throwable 异常
                 */
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    if ("deleteUser".equals(method.getName())) {
                        // 增强指定方法
                        int id = (int) args[0];
                        id++; //增强参数
                        System.out.println("增强方法体 1/2");
                        String invoke = (String) method.invoke(target, id);
                        invoke = invoke + "!!!"; //增强返回值
                        System.out.println("增强方法体 2/2");
                        return invoke;
    
                    } else {
                        // 其它方法默认实现
                        Object invoke = method.invoke(target, args);
                        return invoke;
                    }
                }
            });
        }
    }

    4. 测试

    @Test
    public void test01() {
        // 创建目标对象
        UserService target = new UserService();
        System.out.println(target.getClass());
        // 创建代理对象
        IUserService proxy = (IUserService) new ProxyFactory(target).createProxyInstance();
        System.out.println(proxy.getClass());
        // 使用代理对象调用方法
        proxy.insertUser();
        String s = proxy.deleteUser(1);
        System.out.println(s);
    }

     四 CGLIB代理(子类代理)

    通过在内存中构建一个子类对象从而实现对目标对象功能的扩展 CGLIB是一个强大的高性能的代码生成包 底层使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类

    优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象与目标对象都不需要实现接口

    缺点: 需要引入CGLIB的JAR文件

    1. 目标对象

    /**
     * 目标对象
     * Created by Hy on 2020/7/10.
     */
    public class UserService {
    
        public void insertUser() {
            System.out.println("insert ok");
        }
    
        public String deleteUser(int id) {
            System.out.println("delete... ... ...");
            return "id = " + id + " delete ok";
        }
    }

    2. 代理工厂

    /**
     * 代理工厂
     * Created by Hy on 2020/7/13.
     */
    public class ProxyFactory {
    
        private Object target; //目标对象
    
        public ProxyFactory(Object target) {
            this.target = target;
        }
    
        public Object createProxyInstance() {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(target.getClass());
            enhancer.setCallback(new MethodInterceptor() {
                /**
                 * 代理对象调用的所有方法都会触发该方法执行
                 * @param proxy 代理对象
                 * @param method 被代理的方法
                 * @param args 被代理的方法传参
                 * @param methodProxy 代理的方法
                 * @return 被代理的方法返回值
                 * @throws Throwable 异常
                 */
                @Override
                public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                    if ("deleteUser".equals(method.getName())) {
                        // 增强指定方法
                        int id = (int) args[0];
                        id++; //增强参数
                        System.out.println("增强方法体 1/2");
                        String invoke = (String) method.invoke(target, id);
                        invoke = invoke + "!!!"; //增强返回值
                        System.out.println("增强方法体 2/2");
                        return invoke;
    
                    } else {
                        // 其它方法默认实现
                        Object invoke = methodProxy.invokeSuper(proxy, args); //等同 method.invoke(target, args);
                        return invoke;
                    }
                }
            });
            return enhancer.create();
        }
    }

    3. 测试

    @Test
    public void test01() {
        // 创建目标对象
        UserService target = new UserService();
        System.out.println(target.getClass());
        // 创建代理对象
        UserService proxy = (UserService) new ProxyFactory(target).createProxyInstance();
        System.out.println(proxy.getClass());
        // 使用代理对象调用方法
        proxy.insertUser();
        String s = proxy.deleteUser(1);
        System.out.println(s);
    }
  • 相关阅读:
    MySQL5.6 GTID、多线程复制
    WPS for Linux(ubuntu)字体配置(字体缺失解决办法)
    linux下用phpize给PHP动态添加扩展
    Zabbix汉化方法
    [FTP] Pure-FTPd SSL/TLS 配置方法
    PHP 缓存扩展opcache
    sftp搭建
    nginx https使用
    iptables基本规则
    kvm虚拟机安装
  • 原文地址:https://www.cnblogs.com/huangyi-427/p/13296006.html
Copyright © 2020-2023  润新知