Spring之代理模式和Spring-IOCDI

代理模式

《租房》

今天是7月1日,我毕业了。

于是我开始准备找工作,但是有一个好消息和坏消息。

好消息是:我找到了一份月薪20000的工作

坏消息是:这工作的地方也太特么远了吧!!!💢💢💢💢

于是我决定再公司附近租一个房子,可是问题是,我找不到房东啊?!!

突然看到电线杆上贴的小广告:“低价租房,接收短租,有意者请联系:173xxxxxxxxxx”,我毫不犹豫拨通了电话

。。。

半个小时后,中介来了,还带我参观了房子,签了合同

Yes!!我租到了!!

。。。过了一个月,我才发现,这特么是个黑中介😇😇😇

静态代理

租房接口Rent

public interface Rent {

    void rent();
}

房东类LandHolder😑

public class LandHolder implements Rent {
    @Override
    public void rent() {
        System.out.println("房东:租房");
    }

}

代理类Mediator🧐

这种代理方式被称为静态代理,因为这个代理只针对一个被代理的对象

比如这个Mediator只能代理LandHolder,因为他不是一个合规中介公司的中介,在合同里面还黑了我800块钱

public class Mediator implements Rent {

    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    @Override
    public void rent() {
        System.out.println("中介:看房");
        System.out.println("中介:签合同");
        rent.rent();
    }
}

我(大冤种🙃🙃)

public class Main {

    public static void main(String[] args) {

        LandHolder landHolder = new LandHolder();
        Mediator mediator = new Mediator();

        mediator.setRent(landHolder);

        mediator.rent();
    }
}

//输出结果
//中介:看房
//中介:签合同
//房东:租房

动态代理:JDK的动态代理

三个月过去,我也从这家公司离职了,不过不是我自己辞职,是被辞退的🤐🤐🤐

理由是:我只会静态代理,不符合公司要求(此时我心里一万批🐴在奔腾)

。。。

于是,我去找了一家正规的中介公司(这家公司叫JDK,并且只支持接口代理的动态代理)

不得不说,中介公司就是强大,什么都能代理,租房、租车,甚至是过年租女朋友…

ok,话说回来,他是怎么实现的呢?

同样的

租房接口Rent

public interface Rent {

    void rent();
}

房东类LandHolder😑

public class LandHolder implements Rent {
    @Override
    public void rent() {
        System.out.println("房东:租房");
    }

}

JDK这家公司就强大在,他给我办理租房服务的时候,会每次都去找到房东对象landHolder ,然后为我去分配处理器invocationHandler ,每次在invocationHandler 中实现办理的逻辑(@Override部分),然后再去创建了proxy代理对象办理业务,真牛逼!!怪不得说什么都能代理呢

public static void JDKProxy(){
        LandHolder landHolder = new LandHolder();

        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("中介:看房");
                System.out.println("中介:签合同");
                method.invoke(landHolder, args);

                return null;
            }
        };

        Class<?>[] interfaces = {Rent.class};

        Rent proxy = (Rent) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, invocationHandler);

        proxy.rent();
    }
}

动态代理:CGLIB的动态代理

就当我办理好的时候,CGLIB这家代理公司也找上了我,说:JDK能动态代理,我也能动态代理,而且我还是基于类的代理…

我次奥,没听说过啊,于是我线下约了中介,他给我介绍说,我们的代码实现是这样的

房东类LandHolder😑

public class LandHolder implements Rent {
    @Override
    public void rent() {
        System.out.println("房东:租房");
    }

}

我:等等?

中介:怎么了?

我:我靠?!接口呢?

中介:我们是基于类的,不需要那套规则,你就放心好了

我:我看看怎么回事…

。。。。

我:所噶寺内~~,首先找到房东对象landHolder ,然后让landHolder 去造了个儿子模板enhancer ,然后在实现处理逻辑的处理器methodInterceptor ,并添加到enhancer ,再让enhancer.create()一个代理对象,最后代理对象帮我办理业务。

public static void CGLIBProxy(){
        LandHolder landHolder = new LandHolder();

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(LandHolder.class);

        MethodInterceptor methodInterceptor = new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("中介:看房");
                System.out.println("中介:签合同");
                method.invoke(landHolder, objects);
                return null;
            }
        };

        enhancer.setCallback(methodInterceptor);
        Rent proxy = (Rent) enhancer.create();
        proxy.rent();

    }

不对,好像JDK和CGLIB的代理也能坑我钱!!!😣😣😣

总结

代理模式,就是在不改变原有代码的基础上,增强功能

简单来说就是,房子仍然是房东出租的,但是在出租前后代理对象能做一些操作,比如租房前带我看房、租房后给我钥匙之类的。。。

代理分为静态代理和动态代理

  • 静态代理

    • 缺点:每次需要代理时就需要创建一个代理对象,代码的重用性低,并且增加了开发成本

      就比如租房就要一个专门代理,租车也需要一个专门代理,老板没钱发工资啊

  • 动态代理

    • 优点:灵活性高,代码重用性提高

      每次的代理的前后逻辑都交给了处理器(invocationHandler /methodInterceptor )去实现,其他的部分都是重复部分,就交给JDK和CGLIB去封装了

Spring的IOC与DI

技术:xml文件 + 反射

IOC(inverse of control):控制反转

DI(dependicies injection):依赖注入

依赖注入有

  • 属性注入(使用set方法)

  • 构造注入(使用构造方法)

在以前的代码中,创建并使用对象是如下

User user= new User();
//构造方法、设置属性...
System.out.println("user = " + user);
//user = User(name=周珍珍, age=18, userInfo=UserInfo(address=成都理工大专, info=历史悠久的恐龙大专), hobbies=[唱歌, 跳舞], friend=[刘旭, 李淑文, 敖国珍], girlFriend=[刘旭], family={李俊瑶=19, 李虹霖=21}, properties={性格=温和, 身高=150})

但是,引入IOC的概念后,谁创建谁管理,所以就将对象的创建和管理的权力交给了Spring,这就是控制反转

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--    声明一个UserInfo对象-->
    <bean class="cn.cnmd.spring.pojo.UserInfo" id="userInfo">
        <property name="address" value="成都理工大专"/>
        <property name="info" value="历史悠久的恐龙大专"/>
    </bean>

    <!--    声明一个User对象-->
    <bean class="cn.cnmd.spring.pojo.User" id="user">
        <!--        简单数据类型-->
        <property name="name" value="周珍珍"/>
        <property name="age" value="18"/>
        <!--引用数据类型-->
        <property name="userInfo" ref="userInfo"/>
        <!--数组类型-->
        <property name="hobbies">
            <array>
                <value>唱歌</value>
                <value>跳舞</value>
            </array>
        </property>
        <!--集合类型-->
        <property name="friend">
            <list>
                <value>刘旭</value>
                <value>李淑文</value>
                <value>敖国珍</value>
            </list>
        </property>

        <property name="girlFriend">
            <set>
                <value>刘旭</value>
            </set>
        </property>

        <property name="family">
            <map>
                <entry key="李俊瑶" value="19"/>
                <entry key="李虹霖" value="21"/>
            </map>
        </property>
        <!--配置文件类型-->
        <property name="properties">
            <props>
                <prop key="性格">温和</prop>
                <prop key="身高">150</prop>
            </props>
        </property>
    </bean>
</beans>

通过applicationContext.xml配置文件的bean的声明,从而让创建对象和管理对象的步骤省略,只需要调用对象

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

User user = (User) applicationContext.getBean("user");
System.out.println("user = " + user);
//user = User(name=周珍珍, age=18, userInfo=UserInfo(address=成都理工大专, info=历史悠久的恐龙大专), hobbies=[唱歌, 跳舞], friend=[刘旭, 李淑文, 敖国珍], girlFriend=[刘旭], family={李俊瑶=19, 李虹霖=21}, properties={性格=温和, 身高=150})

是不是很方便呢?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[OHOS_ERROR]: Please call hb utilities inside ohos source directory

当执行hb set报如下错误时&#xff1a;原因时重新拉取了源码&#xff0c;且源码路径被改了 [OHOS_ERROR]: Please call hb utilities inside ohos source directory 【解决办法】 卸载hb并在源码路径下重新安装 python3 -m pip uninstall ohos-build 安装hb python3 -m pi…

python-逻辑语句

if else语句 不同于C&#xff1a;else if range语句&#xff1a; continue continue的作用是&#xff1a; 中断所在循环的当次执行&#xff0c;直接进入下一次 continue在嵌套循环中的应用 break 直接结束所在的循环 break在嵌套循环中的应用 continue和break&#xff0c;在…

力扣:LCR 024. 反转链表(Java)

目录 题目描述&#xff1a;示例 1&#xff1a;示例 2&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给定单链表的头节点 head &#xff0c;请反转链表&#xff0c;并返回反转后的链表的头节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#x…

【嵌入式DIY实例】- LCD ST7735显示DHT11传感器数据

LCD ST7735显示DHT11传感器数据 文章目录 LCD ST7735显示DHT11传感器数据1、硬件准备与接线2、代码实现本文介绍如何将 ESP8266 NodeMCU 板 (ESP-12E) 与 DHT11 (RHT01) 数字湿度和温度传感器连接。 NodeMCU 从 DHT11 传感器读取温度(以 C 为单位)和湿度(以 rH% 为单位)值,…

1.5 Canal 数据同步工具详细教程

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…

【你也能从零基础学会网站开发】关系型数据库中的表(Table)设计结构以及核心组成部分

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 关系型数据库中…

FTP 文件传输协议:概念、工作原理;上传下载操作步骤

目录 FTP 概念 工作原理 匿名用户 授权用户 FTP软件包 匿名用户上传下载实验步骤 环境配置 下载 上传 wget 授权用户上传下载步骤 root用户登录FTP步骤 监听 设置端口号范围 修改用户家目录 匿名用户 授权用户 FTP 概念 FTP&#xff08;File Transfer Prot…

C语言之线程的学习

线程属于某一个进程 共同点&#xff1a;都能并发 线程共享变量&#xff0c;进程不共享。 多线程任务中&#xff0c;其中某一个线程调用了exit了&#xff0c;其他线程会跟着一起退出 如果是特定的线程就调用pthread_exit 失败返回的是错误号 下面也是

VSCode无法识别 node、npm

一、前提 电脑新安装了node.js&#xff0c;在cmd查看node和npm版本没有问题&#xff0c;但是在VSCode无法识别 1.cmd查看版本&#xff1a; 2.VSCode报错信息&#xff1a; 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果…

C#——Property属性详情

属性 属性&#xff08;Property&#xff09;是类&#xff08;class&#xff09;、结构体&#xff08;structure&#xff09;和接口&#xff08;interface&#xff09;的成员&#xff0c;类或结构体中的成员变量称为字段&#xff0c;属性是字段的扩展&#xff0c;使用访问器&am…

视频转音频:怎样提取视频中的音频?6个提取音频的小技巧(建议收藏)

怎样提取视频中的音频&#xff1f;当我们想从视频中提取出声音时&#xff0c;通常会遇到很多问题。无论是想单独提取出视频里的音频&#xff0c;还是把它转成方便储存或者分享的音频格式&#xff0c;这都会涉及到视频转音频的一个需求。因此&#xff0c;在这篇指南里&#xff0…

如何编写高质量更优雅的代码(Java)

1、函数式接口—FunctionalInterface 好处&#xff1a;高逼格、代码收拢、解藕、统一处理 适用范围&#xff1a;具有共性的接口调用代码 举个栗子&#xff1a; 在我们平时的微服务开发中&#xff0c;调用其他服务的接口&#xff0c;通常要把接口调用部分做异常处理(try catch…

为何交易价格可能超出预期?

当你尝试执行订单时&#xff0c;如果收到“报价超出”的提示&#xff0c;这通常意味着交易无法按你的预期价格成交。对于某些交易者来说&#xff0c;这可能会带来一些困扰&#xff0c;但在外汇等流动性极高的市场中&#xff0c;这种情况是相当常见的。 外汇市场之所以吸引众多…

Python系统教程01

Python 是一门解释性语言&#xff0c;相对更简单、易学&#xff0c;它可以用于解决数学问题、获取与分 析数据、爬虫爬取网络数据、实现复制数学算法等等。 1、print()函数&#xff1a; print()书写时注意所有的符号都是英文符号。print()输出内容时&#xff0c;若要输出字符…

A股低开高走,近3000点,行情要启动了吗?

A股低开高走&#xff0c;近3000点&#xff0c;行情要启动了吗&#xff1f; 今天的A股&#xff0c;让人瞪目结舌了&#xff0c;你们知道是为什么吗&#xff1f;盘面上出现2个重要信号&#xff0c;一起来看看&#xff1a; 1、今天两市低开高走&#xff0c;银行板块护盘指数&…

如何使用AI学习一门编程语言?

无论你是软件开发新手还是拥有几十年的丰富经验&#xff0c;总是需要学习新知识。TIOBE Index追踪50种最受欢迎的编程语言&#xff0c;许多生态系统为职业发展和横向转型提供了机会。鉴于现有技术具有的广度&#xff0c;抽空学习一项新技能并有效运用技能可能困难重重。 最近我…

Linux启动elasticsearch,提示权限不够

Linux启动elasticsearch&#xff0c;提示权限不够&#xff0c;如下图所示&#xff1a; 解决办法&#xff1a; 设置文件所有者&#xff0c;即使用户由权限访问文件 sudo chown -R 用户名[:新组] ./elasticsearch-8.10.4 //切换到elasticsearch-8.10.4目录同级 chown详细格式…

关于vue创建项目失败报错(镜像过期)的解决方案

在新建vue项目时出现以下错误&#xff1a; 原因&#xff1a; npm.taobao.org和registry.npm.taobao.org旧域名于2021年官方公告域名更换事件&#xff0c;已于2022年05月31日零时起停止服务&#xff0c;域名HTTPS证书于2024年1月22日正式到期&#xff0c;不可再用。 解决方案:…

昇思MindSpore学习总结七——模型训练

1、模型训练 模型训练一般分为四个步骤&#xff1a; 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 现在我们有了数据集和模型后&#xff0c;可以进行模型的训练与评估。 2、构建数据集 首先从数据集 Dataset加载代码&#xff0…

gdb及其使用

gdb调试一&#xff1a; 首先进入gdb&#xff0c;确定好进程&#xff0c;输入进程号 确定要调试哪个文件&#xff0c;然后输入&#xff1a;&#xff08;b为打断点&#xff09; (gdb) b serialization_protobuffer.h:write<ros::serialization::OStream>(ros::serializat…