设计模式 —— Proxy 代理模式

简介

  • Proxy代理模式是一种结构型设计模式。通过代理模式可以实现程序之间的解耦,可以解决在直接访问对象时带来的程序之间耦合度增大的问题。
  • 按照代理的创建时期,代理类分为两种:
    • 静态代理:在编译期,手动创建代理类,而不是由编译器生成代理类。
    • 动态代理:在运行期,运用反射机制动态而生成代理类。
      • JDK代理基于接口接口
      • CGlib代理基于继承

静态代理

  • 优点
    • 静态代理可以将目标类和目标方法封装起来,有隐蔽的作用。
  • 缺点
    • 静态代理类只能为特定的接口服务。
    • 如想要为多个接口服务则需要建立很多个代理类。

目录结构

  • cn.water
    • main
      • java
        • IProducer.java(接口)
        • Producer.java(实现类)
        • ProxyProducer.java(代理类)
    • test
      • staticTest.java(测试类)

接口

IProducer.java

package cn.water.StaticProxy;

public interface IProducer {

    /** 销售 */
    void saleProduct(float money);

    /** 售后 */
    void afterService(float money);

}

实现类

Producer.java

package cn.water.StaticProxy;

public class Producer implements IProducer {

    /** 销售 */
    public void saleProduct(float money) {
        System.out.println("生产者:通过[销售],获得了"+money+"元");
    }

    /** 售后 */
    public void afterService(float money) {
        System.out.println("生产者:通过[售后],获得了"+money+"元");
    }
}

代理类

ProxyProducer.java

package cn.water.StaticProxy;

public class ProxyProducer implements IProducer {

    private Producer producer = new Producer();

    /** 销售 */
    public void saleProduct(float money) {
        System.out.println("消费者:消费了"+money+"元");
        producer.saleProduct(money * 0.2f);
    }

    /** 售后 */
    public void afterService(float money) {
        System.out.println("消费者:消费了"+money+"元");
        producer.afterService(2);
    }
}

测试类

staticTest.java

package cn.water.test;

import cn.water.StaticProxy.IProducer;
import cn.water.StaticProxy.Producer;
import cn.water.StaticProxy.ProxyProducer;
import org.junit.Test;

public class staticTest {

    @Test
    public void test(){

        /** 成员变量 */
        final Producer producer = new Producer();
        /** 获取动态代理对象 */
        IProducer proxy =  new ProxyProducer() ;
        /** 调用方法 */
        /* 销售方法经过加强,增强的方法被调用 */
        proxy.saleProduct(999.12f);
        /* 销售方法经过加强,方法不被调用 */
        proxy.afterService(99f);

    }


}

动态代理(JDK)

  • JDK动态代理基于 Java的反射机制 实现。
    • 因为Java的反射机制基于接口,所以目标类一定要有接口。
  • 基于JDK技术动态代理类技术核心:Proxy类InvocationHandler接口。(java.lang.reflect)
    • Proxy类中定义了生成JDK动态代理类的方法 getProxyClass(ClassLoader loader,Class... interfaces),返回class实例代表一个class文件。生成的动态代理类继承Proxy类(重要特性) ,并实现公共接口。
    • InvocationHandler接口 是被动态代理类回调的接口,我们所有需要增加的处理逻辑都添加到 invoke方法里面。
  • 匿名内部类参数必须为final类型

目录结构

  • cn.water
    • IProducer.java(接口)
    • Producer.java(实现类)
  • test
    • staticTest.java(测试类)

接口

IProducer.java

package cn.water.DynamicProxy.jdk;

public interface IProducer {

    /** 销售 */
    void saleProduct(float money);

    /** 售后 */
    void afterService(float money);

}

实现类

Producer.java

package cn.water.DynamicProxy.jdk;

public class Producer implements IProducer {

    /** 销售 */
    public void saleProduct(float money) {
        System.out.println("生产者:通过[销售],获得了"+money+"元");
    }

    /** 售后 */
    public void afterService(float money) {
        System.out.println("生产者:通过[售后],获得了"+money+"元");
    }
}

测试类

staticTest.java

  • Proxy.newProxyInstance方法
    • 加载器
    • 接口
    • InvocationHandler接口
      • invoke方法
        • method:代表方法
        • args:参数
  • 匿名内部类只能访问方法内修饰符为final的参数
    • 为了保持数据的一致性
package cn.water.test;

import cn.water.DynamicProxy.jdk.IProducer;
import cn.water.DynamicProxy.jdk.Producer;
import org.junit.Test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class jdkTest {

    @Test
    public void test(){
        /** 1、成员变量 */
        final Producer producer = new Producer();
        /** 2、获取动态代理对象 */
        IProducer proxy = (IProducer) Proxy.newProxyInstance(
                /* 类加载器 */
                producer.getClass().getClassLoader(),
                /* 实现类的接口 */
                producer.getClass().getInterfaces(),
                /** 增强代码 */
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;
                        /* 方法参数 */
                        Float money = (Float) args[0];
                        /* 方法名 */
                        if ("saleProduct".equals(method.getName())) {
                            /* 调用方法 */
                            System.out.println("消费者:消费了"+money+"元");
                            result = method.invoke(producer, money * 0.2f);
                        }
                        if ("afterService".equals(method.getName())) {
                            /* 调用方法 */
                            System.out.println("消费者:消费了"+money+"元");
                            result = method.invoke(producer, 5);
                        }
                        /* 返回 */
                        return result;
                    }
                }
        );
        /** 3、调用方法 */
        /* 销售方法经过加强,增强的方法被调用 */
        proxy.saleProduct(999.12f);
        /* 销售方法经过加强,方法不被调用 */
        proxy.afterService(999.12f);
    }

}

动态代理(cglib)

目录结构

  • cn.water
    • Producer.java(类)
  • test
    • staticTest.java(测试类)

实现类

Producer.java

package cn.water.DynamicProxy.cglib;

import cn.water.DynamicProxy.jdk.IProducer;

public class Producer {

    /** 销售 */
    public void saleProduct(float money) {
        System.out.println("生产者:通过[销售],获得了"+money+"元");
    }

    /** 售后 */
    public void afterService(float money) {
        System.out.println("生产者:通过[售后],获得了"+money+"元");
    }
}

测试类

  • Enhancer.create方法
    • 字节码
    • MethodInterceptor接口
      • intercept方法
        • method:代表方法
        • args:参数

staticTest.java

package cn.water.test;

import cn.water.DynamicProxy.cglib.Producer;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;


public class cglibTest {

    @Test
    public void test() {
        /** 1、成员变量 */
        final Producer producer = new Producer();
        /** 2、获取动态代理对象 */
        Producer cglibProducer = (Producer) Enhancer.create(
                /* 字节码 */
                producer.getClass(),
                /* CallBack子类 */
                new MethodInterceptor() {
                    /** 增强代码 */
                    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                        Object result = null;
                        /* 方法参数 */
                        Float money = (Float) args[0];
                        /* 方法名 */
                        if ("saleProduct".equals(method.getName())) {
                            /* 调用方法 */
                            System.out.println("消费者:消费了"+money+"元");
                            result = method.invoke(producer, money * 0.2f);
                        }
                        if ("afterService".equals(method.getName())) {
                            /* 调用方法 */
                            System.out.println("消费者:消费了"+money+"元");
                            result = method.invoke(producer, 5);
                        }
                        /* 返回 */
                        return result;
                    }
                });
        /** 3、调用方法 */
        /* 销售方法经过加强,增强的方法被调用 */
        cglibProducer.saleProduct(999.12f);
        /* 销售方法经过加强,方法不被调用 */
        cglibProducer.afterService(999.12f);
    }

}

发布了68 篇原创文章 · 获赞 2 · 访问量 1929

猜你喜欢

转载自blog.csdn.net/qq_40981851/article/details/104178132