Spring之代理模式和Spring-IOCDI

news/2024/7/8 7:34:44 标签: 代理模式, spring, java

代理模式

《租房》

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

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

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

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

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

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

。。。

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

Yes!!我租到了!!

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

静态代理

租房接口Rent

java">public interface Rent {

    void rent();
}

房东类LandHolder😑

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

}

代理类Mediator🧐

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

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

java">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();
    }
}

我(大冤种🙃🙃)

java">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

java">public interface Rent {

    void rent();
}

房东类LandHolder😑

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

}

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

java">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😑

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

}

我:等等?

中介:怎么了?

我:我靠?!接口呢?

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

我:我看看怎么回事…

。。。。

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

java">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方法)

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

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

java">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的声明,从而让创建对象和管理对象的步骤省略,只需要调用对象

java">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.niftyadmin.cn/n/5536775.html

相关文章

C#中PostgreSql操作类的设计

在C#中设计一个PostgreSQL操作类,可以利用Npgsql库,它是PostgreSQL的.NET数据提供者。以下是一个简单的PostgreSQLHandler类设计,它提供了基本的数据库操作,如连接、查询、插入、更新和删除。 Csharp 1using System; 2using Npgsql; 3 4public class PostgreSQLHandler 5{…

scss学习总结

摘录更改至 scss: map:merge 和 each $attribute, $value in $variables 研究 Element-plus 源码时&#xff0c;有以下一段代码&#xff1a; // path: element-plus/packages/theme-chalk/src/button.scss include b(button) {include set-component-css-var(button, $butto…

UE4_材质_材质节点_Fresnel

学习笔记&#xff0c;不喜勿喷&#xff0c;侵权立删&#xff0c;祝愿生活越来越好&#xff01; 一、问题导入 在创建电影或过场动画时&#xff0c;你常常需要想办法更好地突显角色或场景的轮廓。这时你需要用到一种光照技术&#xff0c;称为边沿光照或边缘光照&#xff0c;它的…

第二十一章 网络编程

​ 一、网络的相关概念 1. 网络通信 &#xff08;1&#xff09;网络通信&#xff1a;将 数据 通过网络从一台设备传输到另一台设备 &#xff08;2&#xff09;java.net 包下提供了一系列的类或接口&#xff0c;完成网络通信 2. 网络 概念&#xff1a;两台或多台设备通过一定…

JVM 堆内存结构 年轻代 老年代

堆内存 内存划分 对于大多数应用&#xff0c;Java 堆是 Java 虚拟机管理的内存中最大的一块&#xff0c;被所有线程共享。此内存区域的唯一目的就是存放对象实例&#xff0c;几乎所有的对象实例以及数据都在这里分配内存。 为了进行高效的垃圾回收&#xff0c;虚拟机把堆内存…

【flutter问题记录】 无效的源发行版:17

问题描述 在看开源项目的时候&#xff0c;clone下来后一直编译失败&#xff0c;提示&#xff1a;无效的源发行版:17&#xff0c;看描述大概是jdk的版本问题&#xff0c;但是在Android studio各种指定都无用&#xff0c;网上资料也没有flutter项目的解决方案&#xff0c;最后在…

大厂都在加急招人的大模型LLM,到底怎么学?

大模型如何入坑&#xff1f; 想要完全了解大模型&#xff0c;你首先要了解市面上的LLM大模型现状&#xff0c;学习Python语言、Prompt提示工程&#xff0c;然后深入理解Function Calling、RAG、LangChain 、Agents等 很多人不知道想要自学大模型&#xff0c;要按什么路线学&a…

在Linux上查找文件的2个好用的命令

1. locate xx &#xff08;查找带xx字符的所有文件或目录&#xff09; 在终端输入命令 locate lua&#xff0c;可以看到&#xff0c;所有带lua字符的文件或目录都会被搜索出来。 2. find / -name xx &#xff08;查找名为xx的文件或目录&#xff09; 在终端输入命令 find …