静态代理和动态代理

2023-09-22 11:53:48

一、静态代理

代理模式(Proxy Pattern)是一种结构型设计模式,它的概念很简单,它通过创建一个代理对象来控制对原始对象的访问。代理模式主要涉及两个角色:代理角色和真实角色。代理类负责代理真实类,为真实类提供控制访问的功能,真实类则完成具体的业务逻辑。这样,当我们不方便或者不能直接访问真实对象时,可以通过代理对象来间接访问。是一种AOP编程思想。

下面,我们以购买火车票为例,我们可以通过火车站去买票,当一些人不方便时候,可能会通过代售点买票,那么代售点其实可以理解为火车站的代理类,只不过代售点提供了火车站的服务,当然也会收取一定的服务费。

代码如下:

public class hook {
    /**
     * 售票服务接口
     */
    public interface TicketService {

        //售票
        public void sellTicket();

    }

    /**
     * 售票服务接口实现类,车站
     */
    public static class Station implements TicketService {

        @Override
        public void sellTicket() {
            System.out.println("\n\t售票.....\n");
        }
    }

    /**
     * 车票代售点
     *
     */
    public static class StationProxy implements TicketService {

        private final Station station;

        public StationProxy(Station station){
            this.station = station;
        }

        @Override
        public void sellTicket() {

            // 1.做真正业务前,提示信息
            System.out.println("××××您正在使用车票代售点进行购票,每张票将会收取5元手续费!××××");
            // 2.调用真实业务逻辑
            station.sellTicket();
            // 3.后处理  println
            System.out.println("××××欢迎您的光临,再见!××××\n");
        }
    }


    public static void main(String[] args) {
        Station changchun = new Station();

        StationProxy proxy = new StationProxy(changchun);

        proxy.sellTicket();

    }


}

通过以上的代码,还是很容易理解静态代理了,通过代理类去控制实体类的行为,并可以灵活加上之自己的行为~ 

二、动态代理

在Java中,动态代理是通过InvocationHandler接口,重写invoke函数实现的。

还是以火车站售票为例,

代码如下:

package com.tiancity.dom.lib;

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

public class dynamic {
    /**
     * 售票服务接口
     */
    public interface TicketService {

        //售票
        public void sellTicket();

    }

    /**
     * 售票服务接口实现类,车站
     */
    public static class Station implements TicketService {

        @Override
        public void sellTicket() {
            System.out.println("\n\t售票.....\n");
        }
    }

    /**
     * 车票代售点
     *
     */
    public static class StationProxy implements InvocationHandler {

        private final TicketService station;

        public StationProxy(TicketService station){
            this.station = station;
        }

        //com.sun.proxy.$Proxy0 cannot be cast to
        //getInterfaces 获取的是接口,不是类,所以要用TicketService
        public Object getProxy(){
            return (Object) Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    station.getClass().getInterfaces(),this);
        }


        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
           if(method.getName().equals("sellTicket")){
               // 1.做真正业务前,提示信息
               System.out.println("××××您正在使用车票代售点进行购票,每张票将会收取5元手续费!××××");
               // 2.调用真实业务逻辑
               result=method.invoke(station, args);
               // 3.后处理  println
               System.out.println("××××欢迎您的光临,再见!××××\n");
           }
            return result;
        }
    }


    public static void main(String[] args) {
        TicketService dalian = new Station();

        StationProxy proxy = new StationProxy(dalian);

        TicketService p = (TicketService) proxy.getProxy();

        p.sellTicket();

    }

}

三、总结

代理模式可以在不修改真实类代码的情况下,实现对真实类的访问控制、性能优化等功能。Java 中有两种实现代理模式的方法:静态代理和动态代理。静态代理需要在编译之前手动编写代理类,而动态代理可以在运行时动态生成代理类。

更多推荐

KMP算法

卡尔老师视频链接KMP算法:KMP算法,全称为Knuth-Morris-Pratt算法,是一种用于字符串匹配的高效算法。它的主要思想是利用已经匹配过的字符信息,避免不必要的回溯,从而提高匹配的效率。KMP算法的核心是构建一个辅助数组next,用来记录模式串中每个字符对应的最长公共前缀和后缀的长度。通过这个数组,可以在匹

(二十七)mmdetection实用工具: Visualization

目录一、基础绘制接口二、基础存储接口三、任意点位进行可视化一、基础绘制接口可视化器(Visualizer):可视化器负责对模型的特征图、预测结果和训练过程中产生的结构化日志进行可视化,支持Tensorboard和WanDB等多种可视化后端。importtorchimportmmcvfrommmengine.visual

口袋参谋:新品上架如何做市场调查?这个方法超实用

很多商家在新品上架之前,都会对宝贝的市场行情进行调查分析,只有了解指定关键词下的行业市场数据,了解消费者需求,才能针对性的进行卖货。可是我们要是人工一点点去搜集,一点点去翻找,很多数据是没法进行人工去统计的,如果你要这样做的话,新品上架那是遥遥无期了。​那还有更好的办法吗?有些商家会专门去购买生意参谋里的市场洞察,对于

Linux cp命令使用指南:详细教程及实际应用场景解析

文章目录Linux中的cp命令使用指南1.简介1.1Linux操作系统简介1.2文件系统和目录结构1.3cp命令概述2.cp命令基本用法2.1复制文件2.2复制目录2.3复制多个文件或目录2.4递归复制2.5强制覆盖已存在文件2.6保留文件权限和属性3.高级用法3.1保留符号链接3.2仅复制更新的文件3.3拷贝到远程主

【Redis】深入理解 Redis 持久化机制 —— RDB 和 AOF

文章目录一、Redis的持久化二、RDB持久化机制2.1对RBD的认识RDB的概念RDB持久化机制的优缺点RDB的相关配置2.2RDB的触发时机2.2RDB的触发时机自动触发手动触发:SAVE和BGSAVE2.3RDB文件的处理保存RDB文件压缩RDB文件校验RDB文件三、AOF持久化机制3.1对AOF的认识AOF的概

【SLAM】视觉SLAM简介

【SLAM】视觉SLAM简介task04主要了解了SLAM的主流框架,清楚VSALM中间接法与直接法的主要区别在什么地方,其各自的优势是什么,了解前端与后端的关系是什么1.什么是SLAM2.VSALM中间接法与直接法的主要区别在什么地方,其各自的优势是什么?在SLAM(SimultaneousLocalizationa

Rsync学习笔记1

企业架构Web服务器的文件及时同步:1)能够理解为何要服务器的文件同步;2)能够简单描述实现文件同步的几种方式;3)能够实现服务器文件实时同步的案例;服务器同步文件的必要性:当业务代码发生改变,上传到web服务器的时候,因为架构已经不是单台服务器提供服务,而是由多台Web服务器提供服务,业务代码需要同时上传到多台Web

2023数学建模研赛华为杯E题思路-出血性脑卒中临床智能诊疗建模

E题出血性脑卒中临床智能诊疗建模三、请建模回答如下问题1血肿扩张风险相关因素探索建模。a)请根据“表1”(字段:入院首次影像检查流水号,发病到首次影像检查时间间隔),“表2”(字段:各时间点流水号及对应的HM_volume),判断患者sub001至sub100发病后48小时内是否发生血肿扩张事件。结果填写规范:1是0否

【Spring】BeanName 的自动生成原理

🎈博客主页:🌈我的主页🌈🎈欢迎点赞👍收藏🌟留言📝欢迎讨论!👏🎈本文由【泠青沼~】原创,首发于CSDN🚩🚩🚩🎈由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!🌠个人主页目录🌟一、默认name生成原理🌟二、id和name属性处理原理🌟一、默认name生成原理在

【C++深入浅出】日期类的实现

目录一.前言二.日期类的框架三.日期类的实现3.1构造函数3.2析构函数3.3赋值运算符重载3.4关系运算符重载3.5日期+/-天数3.6自增与自减运算符重载3.7日期-日期四.完整代码一.前言通过前面两期类和对象的学习,我们已经对C++的类有了一定的了解。本期我们的目标是实现一个完整的日期类,通过实现日期类的构造函数

蓝桥杯 题库 简单 每日十题 day7

01啤酒和饮料题目描述本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐酒。#include<stdio.h>#include<stdlib.h>intmain()

热文推荐