Java----代理

news2024/11/26 23:18:50

什么是代理?

         在Java中,代理是一种用于创建一个或多个服务的中间层,它可以拦截并处理程序对实际服务对象的请求。代理模式是一种设计模式,属于结构型模式,它允许程序员在不修改实际对象代码的情况下,增强或控制对它的访问。

Java中的代理可以分为以下几种类型:

1.静态代理

静态代理在编译时就已经确定代理类和原始类的关系。代理类通常与原始类实现相同的接口,然后在代理类中维护一个原始对象的引用,从而可以在调用原始对象方法前后添加额外的处理逻辑(例如日志记录、权限校验等)。


interface IService {
    void doSomething();
}


class Service implements IService {
    public void doSomething() {
        System.out.println("执行业务逻辑");
    }
}


class ServiceProxy implements IService {
    private IService service;

    public ServiceProxy(IService service) {
        this.service = service;
    }

    public void doSomething() {
        System.out.println("前置处理");
        service.doSomething();
        System.out.println("后置处理");
    }
}

2.动态代理

动态代理是在运行时动态创建的代理方式,不需要在编译时确定代理类。Java提供了java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来支持动态代理。动态代理可以代理任何实现了接口的类。

我们需要准备我们对象:

package com.wxy.proxy;

//将需要代理操作的方法声明在接口中,并继承该接口
public class BigStar implements Star{

    public BigStar() {
    }

    public BigStar(String name) {
        this.name = name;
    }

    @Override
    public String sing(String name) {
        System.out.println(name + "正在唱歌");
        return "表演唱歌完毕";
    }

    @Override
    public String dance(String name) {
        System.out.println(name + "正在跳舞");
        return "表演跳舞完毕";
    }

    private String name;

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "BigStar{name = " + name + "}";
    }
}

将我们需要拓展功能的方法声明在接口中,并让原来的类继承它:

package com.wxy.proxy;

//声明对应的代理方法
public interface Star {
    String sing(String name);
    String dance(String name);
}

然后我们就可以开始编写代理类了,需要注意是该内部类的involk方法是在测试类中使用代理(接口star对象)调用其方法时,会自动调用其involk方法,该involk有三个参数,在源码是这样描述的:

proxy -方法上调用方法的代理实例-对应于代理实例上调用的接口方法的方法实例。

Method对象的声明类将是在其中声明方法的接口,该接口可能是代理类继承该方法所通过的代理接口的超接口。

Args -一个对象数组,其中包含在代理实例的方法调用中传递的参数值,如果接口方法不接受参数,则为空。基本类型的参数被包装在适当的基本包装类的实例中,例如java.lang.Integer或java.lang.Boolean。

package com.wxy.proxy;

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

//代理工具类
public class ProxyUtil {

    //使用静态修饰方便调用,可直接使用类名进行调用
    public static Star createProxy(BigStar bigStar){
        //对我们需要进行代理的方法构建代理对象
        Star star = (Star) Proxy.newProxyInstance(
                //参数一:用于指定使用哪个类去加载生成加载的代理类,指定加载器,这里我们直接使用当前类的加载器
                ProxyUtil.class.getClassLoader(),
                //参数二:需要代理的字节码对象数组,指定接口这些接口指定生成的代张什么样,也就是说有哪些方法需要代理
                new Class[]{Star.class},
                //参数三:用来指定生成的代理对象要干什么事情,可用Lambda表达式进行简化
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().equals("sing")){
                            System.out.println("现在是唱歌业务");

                        }else if(method.getName().equals("dance")){
                            System.out.println("现在是跳舞业务");
                        }
                        System.out.println("做好前置工作");
                        //这里才是我们正在要改造的方法,我们在这里通过反射的方法运行我们原先的代码
                        String result = (String) method.invoke(bigStar, args);
                        System.out.println("做好后置工作");
                        //将原先的返回值进行返回
                        return result;
                    }
                }
        );

        return star;
    }
}

编写测试类查看结果:

package com.wxy.proxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class TestForProxy {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //通过反射的方法来创建我们的对象
        Class<?> classz = Class.forName("com.wxy.proxy.BigStar");
        //指定使用我要使用参数是String类型的构造方法
        Constructor<?> constructor = classz.getDeclaredConstructor(String.class);
        //通过该构造方法我们来创建我们的对象
        BigStar xiaoming = (BigStar) constructor.newInstance("小明");
        //将我们的对象传递给我们的代理,然后拿到代理对象,使用代理对象来调用我们的方法,而不是使用以前的对象调用原先的方法!!!
        Star proxy = ProxyUtil.createProxy(xiaoming);
        System.out.println(proxy.sing(xiaoming.getName()));
        System.out.println(proxy.dance(xiaoming.getName()));
    }
}

输出结果如下:

 

3.CGLIB代理

CGLIB(Code Generation Library)是一个强大的高性能代码生成库,它被用来在运行时生成类的子类,通过方法拦截的方式实现对原始类的增强。CGLIB代理不需要原始类实现任何接口,因此它适用于无法修改源代码的情况。

拓展:

        代理模式在Java中的应用非常广泛,如Spring框架中的AOP(面向切面编程)就是通过代理模式来实现的。代理可以用于多种场景,包括但不限于日志记录、性能监控、事务管理、安全控制等。

总结:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PHP反序列化漏洞从入门到深入8k图文介绍,以及phar伪协议的利用

文章参考&#xff1a;w肝了两天&#xff01;PHP反序列化漏洞从入门到深入8k图文介绍&#xff0c;以及phar伪协议的利用 前言 本文内容主要分为三个部分&#xff1a;原理详解、漏洞练习和防御方法。这是一篇针对PHP反序列化入门者的手把手教学文章&#xff0c;特别适合刚接触PH…

杭州等保测评的备案流程

杭州等级保护备案和测评&#xff0c;构筑了一座坚实的数字安全桥梁&#xff0c;其过程和条件清楚而又重要。这篇文章会详细介绍一些必要的步骤&#xff0c;以帮助你顺利地完成信息系统的安全和合规。 1. 系统识别与自评 在此基础上&#xff0c;首先要明确信息系统所承载的业务…

Zabbix配置监控参考

1 添加host 配置-主机-创建主机 添加主机名&#xff0c;IP&#xff0c;端口 2 添加监控项 配置-主机-监控项 打开后&#xff0c;点击右上角添加监控项&#xff08;进去后。配置想要的监控项目&#xff09; 3 添加CPU监控项 需求&#xff1a;CPU使用率 实现&#xff1…

【基础篇】Docker 容器操作 FOUR

嘿&#xff0c;小伙伴们&#xff01;我是小竹笋&#xff0c;一名热爱创作的工程师。在上一篇文章中&#xff0c;我们探讨了 Docker 镜像管理的相关知识。今天&#xff0c;让我们一起深入了解一下 Docker 容器的操作吧&#xff01; &#x1f4e6; 运行、停止和删除容器 Docker…

归并排序 python C C++ 代码及解析

一&#xff0c;概念及其介绍 归并排序&#xff08;Merge sort&#xff09;是建立在归并操作上的一种有效、稳定的排序算法&#xff0c;该算法是采用分治法(Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff…

商家转账到零钱开通最快捷径

商家转账到零钱存在一定的捷径&#xff0c;这一捷径将放在文章最后。如果商家希望自行开通&#xff0c;可以按照以下步骤进行申请&#xff1a; 1. 确认主体资格&#xff1a;申请主体必须是公司性质&#xff08;有限公司类型&#xff09;&#xff0c;个体工商户暂不支持申请&…

企业级Linux系统防护

一、企业级Linux系统防护概述 一&#xff09;企业级Linux系统安全威胁 企业级Linux系统安全威胁列表 解决的主要安全威胁安全威胁牵涉到的人员及操作文件系统防护避免有意/无意的文件篡改、越权访问&#xff0c;根用户&#xff08;root&#xff09;权限泛滥企业内部用户误操作、…

【Golang 面试 - 基础题】每日 5 题(九)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

Linux虚拟化技术KVM

文章目录 虚拟化基础什么是虚拟化虚拟化优势虚拟机虚拟机的主要特征Hypervisor类型类型1&#xff1a;裸金属型类型2&#xff1a;宿主型 KVM概述KVM体系结构KVM模块载入后的系统运行模式KVM集中管理和控制宿主机环境准备 安装KVM工具包libvirt包功能libvirt结构图安装KVM相关包C…

SEO优化 prerender-spa-plugin工具使用 踩坑记录

安装prerender-spa-plugin yarn add prerender-spa-plugin 或 npm install prerender-spa-plugin初始配置 后面记录踩的坑 配置路由 const routes [{path: /,redirect: {path: /HomeView},},{path: /home,redirect: {path: /HomeView},},{ path: /HomeView,component: HomeV…

postgresql密码复杂度验证和有效期

前言 为了数据库安全以及应对等保测评等要求&#xff0c;我们需要设置密码复杂度。我们通过passwordcheck模块实现复杂度检测功能。 启用密码复杂度验证 找到自己安装pg库的配置文件目录&#xff0c;修改postgresql.conf vim postgresql.conf修改如下内容 shared_preload_…

2023版IDEA安装通义灵码屡遭挫败:重复尝试,安装依旧失败

目录 背景: 过程: 第一步: 第二步: 第三步: 安装成功: 总结: 通义灵码的优点: 背景: 小编使用的是2023版本IDEA&#xff0c;在安装通义灵码的时候出现了一件很让人头痛的问题&#xff0c;我在IEDA中的插件中心里面去下载&#xff0c;但是当我我安装的进度条加载完成之…

命令行创建git仓库

方法1&#xff1a;初始化自己的仓库 git init创建完成之后可以用ls -a查看是否存在.git文件 如果不想要git仓库&#xff0c;可以使用rm -rf .git删除仓库 方法2&#xff1a;克隆别人的仓库 git clone [http][http]是仓库网址 总体流程 可以看到文件分为四种状态&#xff0c…

windows无法打开添加打印机原因分析及解决方法

在日常办公和生活中&#xff0c;打印机是不可或缺的重要设备。然而&#xff0c;有时在添加打印机的过程中&#xff0c;经常会遇各种问题。今天有个小伙伴问我windows无法打开添加打印机怎么回事&#xff1f;今天就教大家windows无法打开添加打印机原因分析及解决方法。 添加打打…

氧传感器在码头油气回收船岸安全装置中的重要作用

随着全球对环境保护和安全生产要求的日益提升&#xff0c;石化码头的油气回收问题已成为行业关注的焦点。在汽油、航煤、苯、对二甲苯等油品和化学品的装船过程中&#xff0c;大量油气挥发不仅加剧了大气污染&#xff0c;还潜藏着对人体健康的严重威胁。因此&#xff0c;推广和…

芋道以开源之名行下作之事 恬不知耻 标榜自己开源 公开源码+sql 不用再加入知识星球

资源 链接: https://pan.baidu.com/s/1TeuxbAUfLQ5_BqMBF1kniQ?pwdcqud 提 取码: cqud 依次为后端、补充版的sql、前端 此文档内安装部署等一应俱全

天气预报的爬虫内容打印并存储用户操作

系统名称&#xff1a; 基于网络爬虫技术的天气数据查询系统文档作者&#xff1a;清馨创作时间&#xff1a;2024-7-29最新修改时间&#xff1a;2024-7-29最新版本号&#xff1a; 1.0 1.背景描述 该系统将基于目前比较流行的网络爬虫技术&#xff0c;对网站上&#xff08;NowAPI…

数据结构之八大排序(上)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 排序的相关介绍 直接插入排序 希尔排序&#xff08;缩小增量排序&#xff09; 选择排序 …

Datawhale AI夏令营 AI+逻辑推理 Task2总结

Datawhale AI夏令营 AI逻辑推理 Task2总结 一、大语言模型解题方案介绍 1.1 大模型推理介绍 ​ 推理是建立在训练完成的基础上&#xff0c;将训练好的模型应用于新的、未见过的数据&#xff0c;模型利用先前学到的规律进行预测、分类和生成新内容&#xff0c;使得AI在实际应…

【Linux】3.Linux 指令大揭秘:常见八个指令的妙用(下)

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;Linux 指令大揭秘&#xff1a;常见八个指令的妙用&#xff08;下&#xff09; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | …