zoukankan      html  css  js  c++  java
  • 设计模式——代理模式

    1.为什么要使用代理

    2.静态代理

    2.1概念

    2.2代码实现

    1.定义业务接口

    package com.bj.service;
    
    //本代理的接口将要被增强
    public interface ISomeService {
        String doFirst();
        void doSecond();
    }

    2.定义目标类,该类实现了业务接口

    package com.bj.service;
    
    //代理类将要增强的类
    public class SomeServiceImpl implements ISomeService {
    
        @Override
        public String doFirst() {
            System.out.println("执行doFirst方法");
            return "abcd";
        }
    
        @Override
        public void doSecond() {
            System.out.println("执行doSecond方法");
        }
    
    }

    3.定义代理类

    这个类要实现ISomeService接口,并且该代理类要讲接口对象作为一个成员变量,还要定义一个带餐的构造器,这个参数为接口对象。目的是将目标对象引入代理类,以便代理类调用目标类的方法。

    package com.bj.proxy;
    
    import com.bj.service.ISomeService;
    
    public class ServiceProxy implements ISomeService {
    
        private ISomeService target;
    
        public ServiceProxy() { // Source快捷键:alt+shift+s + c
    
        }
    
        public ServiceProxy(ISomeService target) {
            this.target = target;
        }
    
        @Override
        public String doFirst() {
            String result = target.doFirst();
            // 增强:将目标方法返回的全小写字母,转化为全大写
            return result.toUpperCase();
        }
    
        @Override
        public void doSecond() {
            target.doSecond();
        }
    
    }

    4.测试

    package com.bj.test;
    
    import com.bj.proxy.ServiceProxy;
    import com.bj.service.ISomeService;
    import com.bj.service.SomeServiceImpl;
    
    public class MyTest {
    
        public static void main(String[] args) {
            ISomeService target = new SomeServiceImpl();
            ISomeService service = new ServiceProxy(target); // rename:alt+shift+r
            String result = service.doFirst();
            System.out.println(result);
            service.doSecond();
        }
    }

    3.JDK动态代理

    3.1概念

     

     

    3.2代码

    1.定义业务接口ISomeService

    package com.bj.service;
    
    //本代理的接口将要被增强
    public interface ISomeService {
        String doFirst();
        void doSecond();
    }

    2.定义目标类ISomeServiceImpl

    package com.bj.service;
    
    //代理类将要增强的类
    public class SomeServiceImpl implements ISomeService {
    
        @Override
        public String doFirst() {
            System.out.println("执行doFirst方法");
            return "abcd";
        }
    
        @Override
        public void doSecond() {
            System.out.println("执行doSecond方法");
        }
    
    }

    以上两个步骤与静态代理类中代码相同。

    3.测试类

    package com.bj.test;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    import com.bj.service.ISomeService;
    import com.bj.service.SomeServiceImpl;
    
    public class MyTest {
    
        public static void main(String[] args) {
            ISomeService target = new SomeServiceImpl();
            // 由proxy类的newProxyInstance方法生成的一个动态代理对象
            ISomeService service = (ISomeService) Proxy.newProxyInstance(target.getClass().getClassLoader(), // 目标类的类加载器
                    target.getClass().getInterfaces(), // 目标类所实现的所有接口
                    new InvocationHandler() { // 目标类的匿名内部类
    
                        // proxy:代理对象
                        // method:目标方法
                        // args:目标方法的参数列表
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            Object result = method.invoke(target, args);
                            if (result!=null) { //添加if的快捷键:alt+shift+z,3
                                result = ((String) result).toUpperCase(); //抽取一个变量的快捷键 ctrl+shift+l
                            }
                            return result;
                        }
                    }); // rename:alt+shift+r
            String result = service.doFirst();
            System.out.println(result);
             service.doSecond();
        }
    }

    4.CGLIB动态代理

    4.1概念

    4.2代码实现

    1.导入jar包

    2.定义目标类,注意不用实现任何接口

    package com.bj.service;
    
    //目标类:没有实现任何接口
    public class SomeService  {
    
        public String doFirst() {
            System.out.println("执行doFirst方法");
            return "abcd";
        }
    
        public void doSecond() {
            System.out.println("执行doSecond方法");
        }
    
    }

    3.创建代理类的工厂。该类要实现MethodIntercept接口

    package com.bj.factory;
    
    import java.lang.reflect.Method;
    
    import com.bj.service.SomeService;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    
    //注意:使用cglib动态代理,要求目标类不能是final的
    //因为final类是不能有子类的,而cglib动态代理增强的原理是:子类增强父类
    public class CglibFactory implements MethodInterceptor {
        private SomeService target; //1.声明目标类的成员变量,并创建以目标类为参数的构造器,用于接收目标对象
        
        public CglibFactory() {
            
        }
        
        public CglibFactory(SomeService target) {
            this.target = target;
        }
    
        public SomeService myCglibCreator() { //2.定义代理类的生成方法,用于创建代理对象
            Enhancer enhancer = new Enhancer(); 
            //指定父类,即目标类。因为cglib动态代理增强的原理是:子类增强父类
            enhancer.setSuperclass(SomeService.class);
            //设置回调接口对象
            enhancer.setCallback(this);
            //create()方法用于创建cglib动态代理对象方法,即目标类的子类对象
            return (SomeService) enhancer.create();
            
        }
        //回调接口的方法
        @Override //3.定义回调接口方法。对目标类的增强在这里完成
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            Object invoke = method.invoke(target, args);
            if (invoke!=null) {//添加if的快捷键:alt+shift+z,3
                invoke = ((String) invoke).toUpperCase();
            }
            return invoke;
        }
    
    }

    4.测试

    package com.bj.test;
    
    import com.bj.factory.CglibFactory;
    import com.bj.service.SomeService;
    
    public class MyTest {
    
        public static void main(String[] args) {
            SomeService target = new SomeService();
            SomeService service = new CglibFactory(target).myCglibCreator();
            String result = service.doFirst();
            System.out.println(result);
             service.doSecond();
        }
    }

  • 相关阅读:
    谷歌 chrome 和 safari 浏览器 td innerHTML Textbox 部分显示不全
    SQLServer 日期转换字符串格式
    GNU 通用公共授權 第三版
    程序员的十个层次 你属于哪一层?
    一个因为缺少括号()引发的SQL存储过程不能执行的问题。
    关于实现字符串表达式求值
    Windows api数据类型【转载】
    x86—EFLAGS寄存器详解【转载】
    python PIL图像处理
    python学习笔记
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/12109712.html
Copyright © 2011-2022 走看看