首页 > 其他分享 >代理模式

代理模式

时间:2022-12-07 09:47:15浏览次数:29  
标签:target 对象 Object 代理 模式 proxy public

代理模式基本介绍

 

 

 

 

如果不使用代理模式,按照我们传统模式是Client直接调用TargetObject对象。

 

 

静态代理

 

 

思路分析图解

 

 

代码实现

package com.sky.proxy.staticproxy;

// 接口
public interface ITeacherDao {

    void teach(); // 授课的方法
}

package com.sky.proxy.staticproxy;

/**
 * 目标对象
 */
public class TeacherDao implements ITeacherDao {

    @Override
    public void teach() {
        System.out.println(" 老师授课中 。。。。。");
    }
}

package com.sky.proxy.staticproxy;

/**
 * 代理对象
 */
public class TeacherDaoProxy implements ITeacherDao {

    private ITeacherDao target; // 目标对象

    // 通过创建构造器,进行目标对象的设置
    public TeacherDaoProxy(ITeacherDao target) {
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println(" 开始代理 。。。。。"); // 可以添加额外的功能
        target.teach(); // 核心方法
        System.out.println(" 提交 。。。。。"); // 可以添加额外的功能
    }
}
package com.sky.proxy.staticproxy;

/**
 * 客户端
 */
public class Client {

    public static void main(String[] args) {
        TeacherDaoProxy proxy = new TeacherDaoProxy(new TeacherDao()); // 代理对象 和 目标对象
        proxy.teach();
    }
}

 开始代理 。。。。。
 老师授课中 。。。。。
 提交 。。。。。

  

静态代理的优缺点

 

 

动态代理

 

 

动态代理应用实例

 

 

 

代码实现

package com.sky.proxy.dynamicproxy;

/**
 * 接口
 */
public interface ITeacherDao {

    void teach(); // 授课方法
    void sayHi(String name); //
}

package com.sky.proxy.dynamicproxy;

/**
 * 目标对象
 */
public class TeacherDao implements ITeacherDao {

    @Override
    public void teach() {
        System.out.println(" 老师授课中 。。。。 ");
    }

    @Override
    public void sayHi(String name) {
        System.out.println(" hello " + name);
    }
}

package com.sky.proxy.dynamicproxy;

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

/**
 * 代理工厂
 */
public class ProxyFactory {

    private Object target; // 聚合一个目标对象(也就是被代理的对象)

    // 构造器,对target进行初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 给目标对象生成一个代理对象

    /**
     * newProxyInstance(ClassLoader loader,
     *                                           Class<?>[] interfaces,
     *                                           InvocationHandler h)
     *         throws IllegalArgumentException
     *
       说明:
          1.ClassLoader loader:指定当前目标对象使用的类加载器,获取加载器的方法 固定
          2.Class<?>[] interfaces,目标对象实现的接口类型,使用泛型方法确认类型
          3.InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器方法,会把
                                当前执行的目标对象方法作为参数传入。
     * @return
     */
    public Object getProxyInstance(){

        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println(" JDK代理开始。。。 ");
                        // 反射机制调用目标对象的方法
                        Object returnVal = method.invoke(target, args);
                        System.out.println(" JDK代理提交。。。 ");
                        return returnVal;
                    }
                });
    }
}

package com.sky.proxy.dynamicproxy;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {

        // 创建目标对象
        ITeacherDao target = new TeacherDao();

        // 给目标对象,创建代理对象,可以转成ITeacherDao
        ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();

        System.out.println(" proxyInstance = " + proxyInstance);
        System.out.println(" proxyInstance = " + proxyInstance.getClass());

        // 通过代理对象,调用目标对象中的方法
        proxyInstance.teach();
        proxyInstance.sayHi(" JERRY ");

    }
}

 JDK代理开始。。。 
 JDK代理提交。。。 
 proxyInstance = com.sky.proxy.dynamicproxy.TeacherDao@5cad8086
 proxyInstance = class com.sun.proxy.$Proxy0
 JDK代理开始。。。 
 老师授课中 。。。。 
 JDK代理提交。。。 
 JDK代理开始。。。 
 hello  JERRY 
 JDK代理提交。。。

  

Cglib代理

 

 

Cglib代理实现步骤

 

1)需要引入Cglib的jar包

 

 

 

以上是教学视频中引入的jar包,我是引入的下面的jar包

 

jar://D:/test/cglib-nodep-3.3.0.jar!/

 

两者最终实现的效果都是一样的。

 

1)在内存中动态构建子类,注意代理的类不能为final,否则会报错。java.lang.IllegalArgumentException.

 

2)目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法。

 

案例类图

 

 

代码实现

package com.sky.proxy.cglibproxy;

/**
 * 目标对象
 */
public class TeacherDao {

    public String teach() {
        System.out.println(" 老师授课中 。。。。我是cglib代理,不需要实现接口  ");
        return " hello ";
    }


}

package com.sky.proxy.cglibproxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 代理工厂
 */
public class ProxyFactory implements MethodInterceptor {

    private Object target; // 聚合一个目标对象(也就是被代理的对象)

    // 构造器,对target进行初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    // 返回一个代理对象 是 target 对象的代理对象
    public Object getProxyInstance(){
        // 1.创建一个工具类
        Enhancer enhancer = new Enhancer();

        // 2.设置父类
        enhancer.setSuperclass(target.getClass());

        // 3.设置回调函数
        enhancer.setCallback(this); // 这里的this就是intercept方法自己

        // 4.创建子类对象,即代理对象
        return enhancer.create();

    }

    // 重写intercept方法,会调用目标对象的方法
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println(" cglib代理模式。。。开始 ");
        Object returnVal = method.invoke(target,objects);
        System.out.println(" cglib代理模式。。。提交 ");

        return returnVal;

    }


}

package com.sky.proxy.cglibproxy;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {


        TeacherDao target = new TeacherDao();

        TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance();

        String result = proxyInstance.teach();
        System.out.println(" 返回结果 : " + result);

    }
}

 cglib代理模式。。。开始 
 老师授课中 。。。。我是cglib代理,不需要实现接口  
 cglib代理模式。。。提交 
 返回结果 :  hello 

  

代理模式的变体

 

标签:target,对象,Object,代理,模式,proxy,public
From: https://www.cnblogs.com/dongyaotou/p/16962161.html

相关文章

  • RabbitMQ 6种模式的练习,以及知识梳理
    常用的模式有Simple、Work、Fanout、Direct、Topic、Headers,可以通过设置交换机类型和配置参数来实现各个模式简单模式(Simple)工作模式(Work)工作模式是考虑到多个消......
  • c#设计模式-适配器模式
     原文网址:https://www.cnblogs.com/guyun/p/6183346.html一、适配器(Adapter)模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而......
  • 工厂模式
    工厂模式在java中,万物皆对象,这些对象都需要创建,如果创建的时候,直接new对象,就会对该对象耦合严重,加入我们要更换对象,所有new对象的地方都需要修改一遍,明显......
  • 04.(创建型模式)java设计模式之建造者模式
    一、什么是建造者模式使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象,将⼀个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。允许⽤户只通过指定......
  • 设计模式之策略模式
    概述在策略模式中,可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法。在这里,每一个封装算法的类都可以称之为一种策略(Strategy),为了保证这些策略在使用时......
  • 五种常见的电子商务模式对比:B2B、B2C、C2B、C2C、O2O
    前言在接触和谈论到电商产品时,我们常常会听到一些专业术语,比如说B2B、B2C等,那么这些术语具体代表什么含义呢?通过收集和整理网络资料以及个人理解,展开说说:(1)B2B模式B2B(B......
  • 设计模式——23种设计模式
    Java设计模式设计模式:是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。面向对象设计原则都是为了高内聚低耦合原则。编程时基本都要遵守单一......
  • oracle19c pdb 模式下的dataguard 配置[1+1]
    标签(空格分隔):Oracle系列一:配置介绍使用Oracle19c的安装包安装两台主机:系统介绍:CentOS7.9x64cat/etc/hosts--------172.130.216.176[主库]1......
  • GEE推出收费模式,国产遥感云平台大有可为!
    谷歌地球引擎(GoogleEarthEngine,GEE)是一个用于对地理空间数据集进行科学分析和可视化的平台。科学家、研究人员和开发人员可以公开访问PB级的卫星图像和地理空间数据,用于全......
  • Java的两大、三类代理模式
    简述代理,是一种设计模式,主要作用是为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目......