JavaSE的【反射】和【动态代理】

news2024/12/22 16:14:31

作为JavaSE的两个个基础知识,【反射】和【动态代理】被广泛运用到spring、spring boot、mybatis......等等各种地方,等到后面的学习中反复提到这个知识点就会开始懵逼,而且这两个知识点其实也是紧密相连的,很多文章和课程里也并没有把他们联系起来,因此在看代码的时候会非常懵逼,这里我就来把他们联系起来讲讲。

一、反射

1、反射是啥

反射简单来说就是:能把类里的所有东西(包括这个类的父类里的东西)全部解析出来,扒得干干净净、一丝不剩!

那么细讲就是,首先我们创建了一个class类的时候,是先将这个【.class】字节码文件存入磁盘

        然后当我们创建这个类的对象的时候,jvm(java虚拟机)就会去找有没有这么个类,比如创建Student对象,jvm就回去找有没有Student.class这个字节码文件,有的话就把它解析了,然后根据创建的实例化对象来在内存里分配一个对应的对象空间。

        与此同时!!jvm会自动为这个类创建一个【class对象】,一个类只对应产生一个class对象,不管你创建了几个这个类的实例化对象(区分一下【对象空间】和【class对象】,【对象空间】只是给你这个对象一个存放数据的 “空间” )

那么反射!就是获取到【class对象】之后,反向分析该类的每一个对象的信息!!!

那么总结,我们反射的机制,就是要解析class字节码文件,然后获取到【Class对象】,用这个【Class对象】解析各个对象的信息!!!!

2、怎么获取class对象

 首先我们需要导入一个包:【import java.lang.reflect.Method;】

 然后要获取【Class对象】,有三种方式:

方式一:Class c = 类名.class;

//获取Class对象1:
Class c = 类名.class;

方式二:Class c = 对象名.getClass;

//获取Class对象2:
某个类 obj = new 某个类();
Class c = obj.getClass();

方式三:Class c = Class.forName("全限定包名");

这个方法是最常用的

//获取Class对象3:
Class c = Class.forName("包全名");

其中"全限定包名"这样获取:

3、反射获取类里的构造方法

语法:

例子:(我懒得写,直接拿黑马的)

最后,利用反射根据指定的构造方法创建对象

例子:

4、反射获取类的成员变量

语法:

例子:

最后,获取变量值和修改变量值

5、反射获取成员方法

这个是最重要的!!!后面经常用到!!!尤其记住!!!尤其是这个【invoke】方法!!!

语法:

例子:

通常我们最常用的就是获取【所有方法(包括父类)】,那么首先获取到Class对象之后,我们就可以用【Method[ ]】这么一个数组接收这个类的【所有方法】,其中包括【他的父类的方法】

语法格式就是:【Method[ ]  变量  =  class对象.getMethods( )】

//获取Class对象:
Class c = Class.forName("com.xxx.xxx");
//获取所有公共方法:
Method[] methods = c.getMethods();

如果不想获取父类的方法,只要自己的就:【Method[ ]  变量  =  class对象.getDeclareMethods( )】

//获取Class对象:
Class c = Class.forName("com.xxx.xxx");
//获取所有公共方法:
Method[] methods = c.getDeclareMethods();

单个方法(且包括私有)

获取单个方法名称,调用单个Method对象.getName()

获取单个方法的参数名,调用单个Method对象.getParameters()

重点来了!!重点!!!重点!!!重点!!!重点!!!重点!!!重点!!!重点!!!

invoke方法!!!!!

语法:

例子:

首先创建一个类为例子:

package com.czm.tliaswebmanagement.reflect;

public class MyClass {
    private String name;

    //构造方法
    public MyClass(String name){
        this.name = name;
    }

    //公有方法,有参数
    public void sing(String song){
        System.out.println(this.name + "正在唱《" + song + "》");
    }
    //私有方法,并且有返回值
    private String eat(){
        return "老八秘制小汉堡";
    }

}

然后我们现在要通过反射机制,来使用这个类的方法,其中包括一个【公有的sing】和一个【私有的eat】方法

基本准备流程就是:1、获取MyClass的Class对象  2、通过Class对象获取到想要的方法,并用Method对象接收  3、创建MyClass的实例化对象

接下来就是invoke登场了,我们只需要【Method对象.invoke()】就可以使用方法了,然后只需要传入 “一或两” 个参数,如果方法里没有参数就只用传入MyClass的实例化对象(就是把方法参数化,因为反射机制利用invoke是去使用所有这个Method方法,那么假设有class1、class2...这么多个对象,到底是使用哪一个对象的这个Method方法呢?所以得传一个实例化对象);如果这个方法有参数,那就传入第二个参数,是这个方法的参数类型,格式就是【数据类型.class】

那么还有三种情况:

1、正常公用方法,无返回值,那就正常【Method对象.invoke()】就行

2、有返回值,那么记住【Method对象.invoke()】返回的是Object对象

3、私有方法,在使用【Method对象.invoke()】之前必须得先【Method对象.setAccessible(true)】来强制获取权限访问私有方法

完整代码:(注意:运行的时候要throws Exception抛出一下异常)

package com.czm.tliaswebmanagement.reflect;
import java.lang.reflect.Method;

public class TestReflect {
    public static void main(String[] args) throws Exception {
        //获取Class对象
        Class c = Class.forName("com.czm.tliaswebmanagement.reflect.MyClass");

        //分别获取这个类的getter方法、sing方法和eat方法
        //.getDeclaredMethod()第一个参数是方法名,(有参数的情况下)第二个参数是这个方法的参数的类型,就是【数据类型.class】
        Method singMethod = c.getDeclaredMethod("sing", String.class);
        Method eatMethod = c.getDeclaredMethod("eat");

        //创建一个这个类的对象,然后调用【Method对象.invoke()】来调用类里的方法
        //invoke()的第一个参数是【这个类的实例化对象】,(该方法有参数的情况)第二是方法里的参数值
        MyClass myClass = new MyClass("KobeManba");
        singMethod.invoke( myClass, "See you agin" );

        //这里别忘了,因为我们把eat方法设置成private私有方法
        //所以我们需要用【Method对象.setAccessible(true)】来强制获取权限访问私有方法
        eatMethod.setAccessible(true);
        Object str1 = eatMethod.invoke( myClass ); //然后有返回值的方法,通过invoke会返回成Object数据
        String str2 = (String) eatMethod.invoke( myClass );  //那如果我们知道返回值是什么类型,就可以直接强制类型转化就行了

        System.out.println(str1);
        System.out.println(str2);
    }
}

二、动态代理

1、动态代理是啥

举个通俗易懂的例子:

假设大明星杨超越的工资只有两个事,唱歌、跳舞,那么在她的唱歌跳舞工作中,除了唱歌跳舞,还有一些前期准备比如:准备话筒、收钱.....

但是杨超越作为一个歌星,她只想要干好唱歌跳舞这两件纯粹的事就行,准备话筒、收钱.....这些事她不想干

 那她就要找一个经纪公司、中介公司来帮她打理这些繁琐事,让她能够专心去唱歌跳舞。那么加入这个时候一个节目组或者一个音乐主办方来找杨超越出席表演唱歌跳舞,杨超越就会说:“你去找我经纪人,别来烦我”,然后主办方去找经纪人来请她唱歌跳舞,但是......经纪人怎么会唱歌跳舞呢?经纪人只会帮忙准备话筒、收钱...干这些琐碎事。

那么经纪人就必须得有对应解决唱歌跳舞的处理方法,除了干准备话筒、收钱...干这些琐碎事,当有主办方找她协商唱歌跳舞的事,经纪人就得把这些事情整理好找到杨超越,跟她协商好然后请她出面完成唱歌跳舞的表演

那么经纪人去处理对应解决唱歌跳舞的处理方法就是唱歌跳舞这个功能的接口,然后杨超越就要有实现这些接口的实现方法。

2、怎么弄?

上面例子说得轻松,但是其实要真正代码实现还是不容易,我们先好好再举个例子好理解

首先我们要先设置一个【接口】,我们理解为【一个明星基本要具备的唱跳能力、业务】吧,首先我们要包装一个明星,你必须得具备一个能唱歌跳舞的能力业务吧?那具体是什么类型风格的唱歌、跳舞还得根据明星自己来实现。

例子代码:

package com.czm.tliaswebmanagement.proxy;

public interface Star {
    /**
     * 代理接口调用【唱歌】方法
     * @param songName
     * @return
     */
    String sing(String songName);

    /**
     * 代理接口调用【跳舞】方法
     */
    void dance();
}

然后就是创建一个【实现类】了,让一个明星去实现这些唱跳能力,这里我设置了它的starName明星名字这个成员变量,然后就是具体实现唱歌和跳舞的方法

package com.czm.tliaswebmanagement.proxy;

public class BigStar implements Star {
    private String starName;

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

    /**
     * 大明星实现【唱歌】
     * @param songName
     * @return
     */
    @Override
    public String sing(String songName) {
        System.out.println(this.starName + "本人正在唱《" + songName + "》");
        return "结束后发布官方微博:“谢谢歌迷支持这场演唱会!”";
    }

    /**
     * 大明星实现【跳舞】
     */
    @Override
    public void dance() {
        System.out.println(this.starName + "本人正在跳舞......");
    }
}

然后重点来了!!最难的部分!!!

我们需要创建一个【代理工具大类】,我们理解为【代理公司、经纪人公司】,你明星找经纪人也不可能直接找一个人当吧?肯定得去一个经纪公司签订合同,然后再选经纪人。那么这里【代理工具大类】就是这样,里面存在对应各种类的【代理、经纪人】,也就是【代理类

那么接下来就是怎么去写这些【代理、经纪人】,也就是【代理类】了,首先这些【代理类】都是这个【代理工具大类】的【静态方法】,是因为写成【静态方法】的形式就可以直接通过【代理工具大类.静态方法( )】这样创建【代理类的实例化对象

补充一下知识点,老实说我之前学java也直接跳过了这里.......

;

我们都知道,如果要创建一个类的【内部类】的实例化对象很麻烦,首先你得先创建这个类的对象,然后再根据这个对象创建这个内部类的对象,而且写法【外部类.内部类  对象名  =  外部类对象. new 内部类()】还很容易错;

;

那么【静态方法】创建实例化对象就很方便,直接【静态方法的返回值类型  对象名  =  外部类.静态方法()】,创建静态方法也很简单,记得加上static修饰符和记得return一个对象出去就行。

public class OuterClass{
    public class innerClass{
        //这是一个内部类
    }

    public static OuterClass innerMethod( 参数 ){
        //这是一个静态方法
        return new OuterClass();
    }
}

//在外部创建它两的实例化对象
//创建内部类innnerClass的对象
OuterClass c = new OuterClass();
OuterClass.innerClass inner1 = c. new innerClass();

//创建静态方法innerMethod的对象
OuterClass inner2 = OuterClass.innerMethod( 参数 );

然后,因为我们需要在外部调用创建这个静态方法的实例化对象,再次注意是这个【代理工具大类】的【代理类】的实例化对象,而不是【代理工具大类】的实例化对象,那么就得【代理工具大类.静态方法( )】这样创建对象。

然后这还只是【代理类】的 “外形”,你得好好修炼、培训一下吧,不能单有有个 “人形”,你还得有内部的 “能力”吧?而且我们也知道【静态方法】创建的对象,必须得在静态方法里return一个对象,那么我们就得再好好写一个【代理类对象】,通过【代理类】这个静态方法return出去。

那么接下来看怎么把这里里面这个【代理类对象】创建。

简单来分析,很简单就是【Proxy.newProxyInstance( )】这个方法,就能生成一个【代理类对象】,但是注意【Proxy.newProxyInstance( )】返回的是一个Object类型对象,我们要变成我们想要的【代理类对象】,就得用它要代理的那个类的接口对象来接收,注意是接口!具体为什么其实我也不知道,反正大家记住就行,就当是一种规范吧,然后用 (接口) 这样强制类型转换,将Object转换成接口类型的对象,就成功“转型”成【代理类对象】了

然后,【Proxy.newProxyInstance( )】这个方法需要接收三个参数:

参数1:用于指定一个类加载器,具体啥意思不用管照抄就行

ProxyUtil.class.getClassLoader()

参数2:指定生成的代理里有哪些方法,一样别管那么多,照抄

new Class[]{Star.class}

参数3:【重要!!】指定代理对象需要干什么

new InvocationHandler() {...}

ok,最后我们剖析最难的最核心的这一个参数,第三个参数,就是它,决定了这个【代理类对象】需要干什么!

那么也就是现在【代理类对象】就是一个完完整整的经纪人了,当我们在外面调用【代理类】的实例化对象(其实也就是调用【代理类对象】)的方法的时候,就相当于一个主办方去委托经纪人去接收处理一下明星的唱歌、跳舞...等等表演,那么经纪人就会利用他的业务能力来处理这些事

那么这里第三个参数,也就是【InvocationHandler()对象】就是他的【业务能力】,那么我们只需要写好一个【InvocationHandler()对象】,在里面写好这个【经纪人、代理】该做的事,然后放到【Proxy.newProxyInstance( )】的第三个参数的位置进去就行了。不过我们通常习惯直接在第三个参数那里通过【new InvocationHandler() { ... }】的方式,直接写好【InvocationHandler()对象】里的内容。

然后这个【InvocationHandler()对象】其实是继承了别的接口,具体是啥我也没细看,总之我们要@Override重写它里面的invoke这个方法,这里注意!!!这个【invoke】方法可不是我们上面学的【反射里的那个invoke】,这里这个【invoke】他只是【InvocationHandler()对象】里的一个内置Api方法,通过看参数也可以看出来,这个【invoke】需要三个参数,而【反射里的那个invoke】是两个参数

然后这给invoke方法需要的三个参数是:

第一个参数:proxy,接收获取外部创建的【代理类】对象,比如

第二个参数:method,代表是【代理类】对象(也就是proxy对象)的哪一个方法,比如

第三个参数:args,代表proxy对象调用方法时传入的参数,比如

整体的invoke方法写法:(记得throws Throwable这个异常)

 最后,完成我们的invoke方法里的内容,既然是【经纪人、代理】该做的事,那么我们就要根据第二个参数(method)来判断,现在外面【代理类】对象调用的是哪一个方法,针对不同的方法做不同的前期准备琐碎事,比如调用唱歌,【经纪人】就要准备话筒、收800万唱歌费;调用跳舞,【经纪人】就要准备场地、服装、收1000万跳舞费......

最后的最后,我们这个【InvocationHandler()对象】的【invoke】方法是【经纪人】干的活,那么回到最初那个问题:【经纪人】他不会唱歌跳舞啊!唱歌跳舞肯定不是他来干,那就只能利用【反射机制!!!!】,用【反射机制的invoke方法】来实现【明星的唱歌跳舞方法

 最后,将这整个【代理类】,也就是【静态方法】return出去,就完成了一个完完整整的代理类了。

完整代码:

package com.czm.tliaswebmanagement.proxy;

import com.czm.tliaswebmanagement.pojo.Emp;
import com.czm.tliaswebmanagement.service.EmpService;
import com.czm.tliaswebmanagement.service.Userservice;
import org.apache.catalina.User;

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

//这是一个【代理工具大类】,这里可以对应不同的 [代理接口],来创建管理不同的【代理类】
public class ProxyUtil {
    //而每一个【代理类】,都是【代理工具大类】的一个【静态方法】,通过【静态方法】可以在外界直接通过【类.静态方法()】的形式创建实例化对象
    //比如外界要创建【createProxy代理类】对象,就这样:Star starProxy = ProxyUtil.createProxy(BigStar实例化对象);
    public static Star createProxy(BigStar bigStar){
        // newProxyInstance(ClassLoader, loaderClass<?>[] interfaces,InvocationHandler h)需要三个参数:
        //参数1:用于指定一个类加载器;
        //参数2:指定生成的代理里有哪些方法;
        //参数3:用来指定生成的代理对象要干什么事情
        // Proxy.newProxyInstance()返回的是一个Object对象,所以我们需要将Object强转成Star接口类型
        Star starProxy = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(), //参数1,照抄就行
                new Class[]{Star.class},          //参数2,一样,别管那么多,照抄
                new InvocationHandler() {         //参数3,指定代理对象需要干什么
                    //这个【invoke】很重要很重要!!它是一个回调函数
                    //但是区别一下这个【不是】下面那个invoke,这个是供代理对象调的invoke方法,只是InvocationHandler的内置api
                    //在外面调用starProxy.sing("断了的弦")  or  starProxy.dance()的时候其实就回调用这个invoke函数
                   
                    //第一个参数proxy,接收获取外部创建的proxy对象,比如starProxy.sing("断了的弦")的【starProxy】
                    //第二个参数method,代表是proxy对象的哪一个方法,比如starProxy.sing("断了的弦")就是【sing()方法】
                    //第三个参数args,代表proxy对象调用方法时传入的参数,比如starProxy.sing("断了的弦")就是【“断了的弦”】
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //代理需要干的事,这个代理类对象会调用不同的代理方法:starProxy.sing("断了的弦")、starProxy.dance()
                        //判断proxy对象调用的是哪一个方法,针对不同的方法来做“代理该干的琐碎事”
                        //比如主办方说要请杨超越唱歌,那就先准备话筒、收取费用
                        if ( method.getName().equals("sing") ){
                            System.out.println("代理开始干活:准备话筒,【唱歌】要收费800万出场费");
                        }else if ( method.getName().equals("dance") ){
                            System.out.println("代理开始干活:准备场地、服装,【跳舞】收费1000万一场");
                        }
                        //那么我们学过了【反射机制的invoke方法】,可以知道要使用【某个对象】里的【某个方法】
                        //那就利用【Method对象.invoke(该对象, 这个Method方法的参数)】
                        //再次提醒,【Method对象】就代表要调用的那个【方法】
                        //invoke第一个参数是这个类的一个实例化对象,也就是指明是调用【哪一个对象】的【这个方法】
                        //invoke第二个参数是这个方法的参数,那么直接用这外层“大invoke”方法里的args参数就行
                        return method.invoke(bigStar, args);
                    }
                }
        );

        return starProxy;
    }
}

接着我们在外面测试一下,先创建一个普通的接口实现类对象(实现“明星”接口的“明星类”),然后用我们刚刚写的【代理工具大类.静态方法( )】——>【ProxyUtil.createProxy()】,传入刚刚那个普通的接口实现类对象(实现“明星”接口的“明星类”),就创建出了一个【代理类对象

最后利用【代理类对象】去调用各种方法,比如【sing()】【dance()】这些方法,就会在执行完【代理类对象】针对【sing()】【dance()】所要做的事之后,紧接着完成普通的接口实现类对象(实现“明星”接口的“明星类”)里真正的【sing()】【dance()】

完整代码:

package com.czm.tliaswebmanagement.proxy;

public class Test {
    public static void main(String[] args){
        //创建一个【明星】对象
        BigStar bigStar = new BigStar("杨超越");

        //然后创建一个【代理类】对象
        Star starProxy = ProxyUtil.createProxy(bigStar);
        //调用这个【代理类】对象的【sing唱歌方法】
        String rs = starProxy.sing("断了的弦");
        System.out.println(rs);
        //调用这个【代理类】对象的【dance跳舞方法】
        System.out.println();
        starProxy.dance();
    }
}

 其实我说到这,感觉自己废话很多,写了一坨屎,但是我也没办法,我只会用这样非常详尽的方法来讲明白这之间的逻辑,最后附上两张图,自行理解吧(点击放大来查看)

感谢观看

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

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

相关文章

零基础STM32单片机编程入门(三十七) MPU6050陀螺仪传感器详解及实战源码

文章目录 一.概要二.MPU6050芯片介绍1.MEMS传感器原理2.MPU6050芯片简介3.芯片引脚定义4.XYZ轴方向5.芯片内部框图6.芯片常用寄存器 三.MPU6050模块原理图及与模块接口定义使用四.STM32单片机驱动MPU6050读取加速度角速度值实验五.CubeMX工程源代码下载六.小结 一.概要 MPU605…

嵌入式面经篇六——寄存器与存储器

文章目录 前言一、寄存器与存储器1、ARM 的 31 个通用寄存器 R0~R15 中&#xff0c;程序计数器 PC 为 R15、程序链接寄存器 LR 为 R14、堆栈指针寄存器 SP 为 R13。2、寄存器掉电会丢失数据吗&#xff1f;3、NOR Flash 与 NAND Flash 的区别&#xff1f;4、SRAM、DRAM、SDRAM的…

使用Python创建省份城市地图选择器

在这篇博客中&#xff0c;我们将探讨如何使用Python创建一个简单而实用的省份城市地图选择器。这个项目不仅能帮助我们学习Python的基础知识&#xff0c;还能让我们了解如何处理JSON数据和集成网页浏览器到桌面应用程序中。 C:\pythoncode\new\geographicgooglemap.py 全部代码…

Camtasia 2024破解版安装教程+汉化补丁激活2024 破解版激活码

最近&#xff0c;我在网上冲浪的时候&#xff0c;发现了一款录屏软件——Camtasia 2024。它不仅功能丰富&#xff0c;而且操作简单&#xff0c;简直是我的录屏利器&#xff01;今天&#xff0c;我就来给大家分享一下这款软件的最新功能&#xff0c;让你们也感受一下它的魔力&am…

【LeetCode:3137. K 周期字符串需要的最少操作次数 | 哈希表 + 子串计数】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

政务网站(.gov)专用SSL/HTTPS证书

政府网站在选择SSL证书时不仅需要遵循网络安全法规以及密评整改&#xff0c;更要提升公众信任度。国产服务商提供的专业版SSL证书&#xff0c;全方位符合政务部门对SSL证书的要求 1 算法要求 政务服务网站需要落实等保制度、密评制度&#xff0c;在密码应用上可选择国密算法S…

从0到1教你搭建Android自动化python+appium环境(超详细~)

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、需要软件 1. JDK:JAVA安装后配置JDK环境 2. SDK:SDK下载后配置adb环境 3. Python:pyhton语言 4. Pycharm:python脚本编译工具 5. Appium-python-clien…

如何巧妙构建“LDAPS”服务器利用JNDI注入

前段时间看到群友问了这样一个问题&#xff1a; ldap:和rmi:关键字被拦截了&#xff0c;是否还可以进行JNDI注入。方法很简单&#xff0c;就是使用ldaps&#xff0c;但后来发现很多人并不知道怎么搭建LDAPS服务器&#xff0c;正好CoNote里有这个功能&#xff0c;写篇简单的文章…

【大模型】LLM工作原理简述

LLM&#xff0c;即large-language-model&#xff0c;大语言模型。 我们可以观察LLM大模型比如豆包在回复的时候&#xff0c;是不是一个一个字&#xff0c;行业里称之为流式输出的方式给你呈现内容的。为什么会这样呢&#xff1f;这是因为&#xff0c;大模型确实是在一个字一个…

Libero编译怪事(1)计数达不到目标值

最近在开发Libero工程&#xff0c;芯片是AGLN250V2。 其中一段计数的程序&#xff0c;声明了一个integer参数。当该参数大于某一值时&#xff0c;执行状态跳转。 编译烧写后&#xff0c;程序一直无法实现跳转。 以为是由于integer是有符号的&#xff0c;可能出现负值&#x…

IDEA中查看接口的所有实现类和具体实现类

1.IDEA中接口的所有实现类查看 1.CTRLH(hierarchy 结构) 我们选中要查看的接口 按住快捷键ctrlh 在界面右侧可以看到该接口的所有可能实现类 2.右击diagrams->show diagram 选中要查看的接口 右击选择diagrams->show diagram 即可以以图表的方式查看接口和所有实现类…

英智金融行业AI Agent,在金融领域全场景下的业务创新与应用实践

随着全球经济的数字化转型&#xff0c;金融行业也在迅速演变。传统的金融服务已经无法完全满足现代客户对快速、个性化和高效服务的需求。与此同时&#xff0c;市场竞争的加剧、监管环境的变化以及客户期望的提升&#xff0c;促使金融机构不断寻求新的技术来优化运营效率、提升…

设计模式---简单工厂模式

简单工厂模式&#xff08;Simple Factory Pattern&#xff09; 是一种创建型设计模式&#xff0c;它定义了一个工厂类&#xff0c;通过这个工厂类可以创建不同类型的对象。简单工厂模式的主要目的是将对象的创建逻辑集中在一个地方&#xff0c;简化客户端的代码&#xff0c;使得…

代码复现改进

代码复现&#xff0c;文献复现&#xff0c;文章复现&#xff0c; 算法复现&#xff0c;科研复现 Matlab,Python中英文均可 保证质量&#xff0c;加快你的研究速度 代码改进跑通&#xff0c;模型优化改进

Java - IDEA开发

使用IDEA开发Java程序步骤&#xff1a; 创建工程 Project&#xff1b;创建模块 Module&#xff1b;创建包 Package&#xff1b;创建类&#xff1b;编写代码&#xff1b; 如何查看JDK版本 Package介绍: package是将项目中的各种文件,比如源代码、编译生成的字节码、配置文件、…

Linux驱动开发基础(设备树)

所学来自百问网 目录 1. 引入设备树的原因 2. 设备树语法 2.1 Devicetree格式 2.1.1 DTS文件格式 2.1.2 node的格式 2.1.3 properties的格式 2.1.4 dts 文件包含dtsi文件 2.2 常用属性 2.2.1 #address-cells、#size-cells 2.2.2 compatible 2.2.3 model 2.2.4 st…

使用 Go 语言将 Base64 编码转换为 PDF 文件

使用Go语言将PDF文件转换为Base64编码-CSDN博客文章浏览阅读104次&#xff0c;点赞2次&#xff0c;收藏5次。本文介绍了如何使用 Go 语言将 PDF 文件转换为 Base64 编码&#xff0c;并保存到文件中。https://blog.csdn.net/qq_45519030/article/details/141224319 在现代编程中…

一、前后端分离通用权限系统(1)

&#x1f33b;&#x1f33b; 目录 一、项目介绍1.1 项目简介1.1.1 项目特色1.1.2 项目背景1.1.3 前置知识1.1.4 项目大纲 1.2 项目详细介绍1.2.1 介绍1.2.2 核心技术1.2.3 项目模块1.2.4 数据库设计 二、搭建环境2.1、搭建项目结构2.1.1、搭建父工程 gansu-auth-parent2.1.2、搭…

Unity 求坐标点在扇形区域内的投影

视频效果&#xff1a; 代码: /// <summary>/// 投影在扇形区域内的点/// </summary>/// <param name"targetPos">目标点</param>/// <param name"fanRadius">扇形半径</param>/// <param name"fanAngle"…

企业为什么需要安装加密软件

1. 数据保护 防止数据泄露&#xff1a;加密软件通过对敏感数据进行加密处理&#xff0c;确保即使数据在传输或存储过程中被截获&#xff0c;也无法被未授权人员读取或利用&#xff0c;从而有效防止数据泄露。 完整性保护&#xff1a;加密不仅保护数据的机密性&#xff0c;还通…