• 代理模式简单实现


    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.
    好处:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.

    代理模型的三种方式
      1. 静态代理
      2. 动态代理  
       JDK动态代理
       CGLIB动态代理

    一、静态代理

      在不修改目标对象方法的基础上,对目标对象方法进行扩展。

      

    package com.lemon.service;
    
    //Service接口
    public interface UserService {
    
        void save();
    
        void delete();
    
        void update();
    
    }
    package com.lemon.service.impl;
    
    import com.lemon.service.UserService;
    
    //Service实现
    public class UserServiceImpl implements UserService {
        @Override
        public void save() {
            System.out.println("新增用户");
        }
    
        @Override
        public void delete() {
            System.out.println("删除用户");
        }
    
        @Override
        public void update() {
            System.out.println("修改用户");
        }
    }
    package com.lemon.a_staticproxy;
    
    import com.lemon.service.UserService;
    
    /**
     * 静态代理类
     * 实现日志扩展功能
     *要求:
     *1)和目标(类)实现同样的接口
     *2)在静态代理类中传入目标对象实例,以便调用目标对象的方法
     *3)可以在静态代理类的方法中添加代理逻辑代码
     */
    public class LogProxy implements UserService{
    
        //接收目标对象实例
        private UserService userService;
    
        //使用构造方法传入目标对象实例
        public LogProxy(UserService userService){
            this.userService = userService;
        }
    
        @Override
        public void save() {
            System.out.println("before=====save");
            //调用目标对象的方法
            userService.save();
            System.out.println("after=====save");
        }
    
        @Override
        public void delete() {
            System.out.println("before=====save");
            //调用目标对象的方法
            userService.delete();
            System.out.println("after=====save");
        }
    
        @Override
        public void update() {
            System.out.println("before=====save");
            //调用目标对象的方法
            userService.update();
            System.out.println("after=====save");
        }
    }
    package com.lemon.a_staticproxy;
    
    import com.lemon.service.UserService;
    import com.lemon.service.impl.UserServiceImpl;
    
    //测试 
    public class Test {
        public static void main(String[] args) {
            //使用静态代理模式
            //1.创建目标对象
            UserService userService = new UserServiceImpl();
            //2.创建静态代理类对象
            UserService proxy = new LogProxy(userService);
            //3.调用代理类的方法
            proxy.save();
            proxy.update();
            proxy.delete();
        }
    }

    静态代理的缺点:

     1)一个静态代理类只能代理一个目标类

        2)静态代理类的每个方法都需要编写重复的代理逻辑,代码比较冗余

    二、JDK动态代理

      前提:目标对象有接口的情况

    package com.lemon.b_jdk_dynamic_proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * 用于生成JDK动态代理对象的工具类
     */
    public class LogProxy {
    
        /**
         * 生成JDK动态代理对象的方法
         *
         * 返回值:生成的JDK动态代理对象
         * 参数:target, 传入目标对象
         */
        public static Object getProxy(Object target){
            /**
             * 参数一:类加载器,JDK动态代理的底层使用类加载器来生成的一个动态类的。通常传入当前类的类加载器即可!!!(LogProxy.class.getClassLoader())
             * 参数二:目标对象的接口列表(所有接口),通常使用目标对象获取接口列表(target.getClass().getInterfaces())
             * 参数三:接口。 该用于编写  代理类的代理逻辑代码。通常我们要提供InvocationHandler接口的实现类(匿名内部类的方式提供)
             */
            return Proxy.newProxyInstance(
                    LogProxy.class.getClassLoader(),
                    target.getClass().getInterfaces(),
                    new InvocationHandler() {
    
                        /**
                         * invoke方法:用于编写 代理类的代理逻辑代码。
                         *      invoke方法在什么时候会被调用?
                         *            该方法会在调用JDK代理对象的每个方法的时候被执行!!!!!
                         *
                         * @param proxy: 生成JDK动态代理对象
                         * @param method: 目标对象的执行方法的对象
                         * @param args: 目标对象的方法参数列表
                         * @return 返回值:目标对象方法执行后的返回结果
                         * @throws Throwable
                         */
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            //获取目标对象的方法名称
                            String methodName = method.getName();
    
                            System.out.println("before======"+methodName);
    
                            //获取方法的参数列表
                           /* if(args!=null)
                            System.out.println(Arrays.asList(args));*/
    
                            //调用目标对象的方法
                            /**
                             * 参数一:执行的对象(必须传入目标对象,不能传入代理对象,否则会死循环)
                             * 参数二:方法的参数列表
                             */
                            Object result = method.invoke(target,args);
    
                            System.out.println("after======"+methodName);
    
                            return result;
                        }
                    }
            );
        }
    }
    package com.lemon.b_jdk_dynamic_proxy;
    
    import com.lemon.service.UserService;
    import com.lemon.service.impl.UserServiceImpl;
    
    /**
     * 演示JDK动态代理
     */
    public class Demo {
    
        public static void main(String[] args) {
            //1.创建目标对象
            UserService userService = new UserServiceImpl();
            //2.创建静态代理类对象
            UserService proxy = (UserService) LogProxy.getProxy(userService);
            //3.调用代理类的方法
            proxy.save();
            proxy.delete();
            proxy.update();
        }
    }

    三、CGLIB动态代理

      目标对象可有可无

    <!-- 导入spring-core(包含cglib依赖) -->
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>5.0.2.RELEASE</version>
            </dependency>
        </dependencies>
    package com.lemon.c_cglib_dynamic_proxy;
    
    
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    /**
     * 用于生成Cglib代理对象的工具类
     */
    public class LogProxy {
    
    
        /**
         * 生成Cglib代理对象
         * 返回值:生成的Cglib子类代理对象
         * 参数:目标对象(目标对象没有接口)
         */
        public static Object getProxy(Object target){
    
            /**
             * 方法返回值:生成的Cglib子类代理对象
             * 参数一:目标对象的类型(target.getClass()) (其实目标对象的类型就是Cglib代理对象 的  父类)
             * 参数二:MethodInterceptor接口,用于编写 代理对象的代理逻辑代码。通常提供MethodInterceptor接口的匿名内部即可
             */
            return Enhancer.create(
                    target.getClass(),
                    new MethodInterceptor() {
                        /**
                         * intercept方法:在调用代理对象的每个方法的时候会执行
                         * @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 {
    
                            //获取目标对象的方法名称
                            String methodName = method.getName();
    
                            System.out.println("before======"+methodName);
    
                            /**
                             * 调用目标对象的方法
                             */
                            //方式一:直接使用目标对象 调用 目标对象的方法
                            Object result = method.invoke(target,args);
                            //方式二:使用代理类(子类)调用 目标对象(父类)的方法
                            //invokeSuper: 调用父类的方法
                            //Object result = methodProxy.invokeSuper(proxy,args);
    
                            System.out.println("after====="+methodName);
    
                            return result;
                        }
                    }
            );
        }
    
    }
    package com.lemon.c_cglib_dynamic_proxy;
    
    import com.lemon.b_jdk_dynamic_proxy.LogProxy;
    import com.lemon.service.UserService;
    import com.lemon.service.impl.UserServiceImpl;
    
    /**
     * 演示JDK动态代理
     */
    public class Demo2 {
    
        public static void main(String[] args) {
            //1.创建目标对象
            UserService userService = new UserServiceImpl();
            //2.创建静态代理类对象
            UserService proxy = (UserService) LogProxy.getProxy(userService);
            //3.调用代理类的方法
            proxy.save();
            proxy.delete();
            proxy.update();
        }
    }
  • 相关阅读:
    MapReduce案例WordCount
    MapReduce排序案例
    MapReduce倒排索引
    MapReduce自定义排序编程
    GroupingComparator 自定义分组
    CombineTextInputFormat小文件处理场景
    cdh 2.6.0版本和apache 2.7.x版本 本地执行环境的差异。
    DistributedCache 分布式缓存
    MapReduce数据压缩机制
    MapReduce其他功能
  • 原文地址:https://www.cnblogs.com/pomelo-lemon/p/11457758.html
Copyright © 2020-2023  润新知