• Spring IOC理论


    2.IOC理论

    2.1 IOC理论推导

    • 在之前的业务中,用户需求的变化会导致原有的业务代码,需要根据用户的需求来修改源代码,程序代码量庞大,修改一次成本太昂贵。
    UserDao/UserDaoImpl/UserOhterSqlDaoImpl
    UserService/UserServiceImpl
    UserServiceImpl{
    	UserDao userDao = new UserDaoImpl(); //这种对象实例方式会用户的调佣不同而经常修改
    	UserDao = new UserOhterSqlDaoImpl();
    }
    //所以创建对象不该由这里的service去决定,而是从外界传入,让调用方去实例实现对象,传入本方法中,从而保证代码不用修改也能做到适应
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 用一个set方法去适应,使用set注入后程序不具有主动性,变成了被动的接受对象

    在调用service方法是注意:有强转现现象,子类自己的方法,不能通过父类变量调用,即多态父类使用子类独有的方法要强转

    UserDao userDao = null;
    public void setUserDao(UserDao userDao){
    	this.userDao = userDao
    }
    
    • 1
    • 2
    • 3
    • 4

    TiP:在传统的 Java 应用中,一个类想要调用另一个类中的属性或方法,通常会先在其代码中通过 new Object() 的方式将后者的对象创建出来,然后才能实现属性或方法的调用。为了方便理解和描述,我们可以将前者称为“调用者”,将后者称为“被调用者”。也就是说,调用者掌握着被调用者对象创建的控制权。

    但在 Spring 应用中,Java 对象创建的控制权是掌握在 IoC 容器手里的,其大致步骤如下。

    1. 开发人员通过 XML 配置文件、注解、Java 配置类等方式,对 Java 对象进行定义,例如在 XML 配置文件中使用 标签、在 Java 类上使用 @Component 注解等。
    2. Spring 启动时,IoC 容器会自动根据对象定义,将这些对象创建并管理起来。这些被 IoC 容器创建并管理的对象被称为 Spring Bean。
    3. 当我们想要使用某个 Bean 时,可以直接从 IoC 容器中获取(例如通过 ApplicationContext 的 getBean() 方法),而不需要手动通过代码(例如 new Obejct() 的方式)创建。
    • IoC 带来的最大改变不是代码层面的,而是从思想层面上发生了“主从换位”的改变。原本调用者是主动的一方,它想要使用什么资源就会主动出击,自己创建;但在 Spring 应用中,IoC 容器掌握着主动权,调用者则变成了被动的一方,被动的等待 IoC 容器创建它所需要的对象(Bean),使系统耦合性降低,让开发更加专注业务的实现,这就是IOC的原型
    • 这个过程在职责层面发生了控制权的反转,把原本调用者通过代码实现的对象的创建,反转给 IoC 容器来帮忙实现,因此我们将这个过程称为 Spring 的“控制反转”。

    设计模式的本质不是为了消除变化,而是为了将变化集中在一个地方

    • IOC解耦的过程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vhyt5P6T-1656508419443)(../typora-user-images/image-20220621134949953.png)]

    2.2 IOC本质

    • Spring IoC的全称是Inversion of Control,称为控制反转,是一种思想,DI(依赖注入)是实现Ioc的一种方法。
    • IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。
    • 传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

    控制反转:核心思想就是由 Spring 负责对象的创建。在对象创建过程中,Spring 会自动根据依赖关系,将它依赖的对象注入到当前对象中,这就是所谓的“依赖注入”。

    • IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。
    • Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2AVYNEl-1656508419444)(../typora-user-images/vjoqi0qk.iju.jpg)]

    • 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
    • 控制反转是通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在spring中实现控制反转是IOC容器,实现方法是依赖注入DI(Dependency Injection)

    2.3 举例理解

    • 实体类
    public class Hello {
        private String message;
    
        public Hello() {
        }
    
        public Hello(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {return false;}
    
            Hello hello = (Hello) o;
    
            return message != null ? message.equals(hello.message) : hello.message == null;
        }
    
        @Override
        public int hashCode() {
            return message != null ? message.hashCode() : 0;
        }
    
        @Override
        public String toString() {
            return "Hello{" +
                    "message='" + message + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 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">
    
       <!--使用spring来创建对象,在spring这些都称为bean
        相当于new对象
        id ==对象名
        class== 对象类型
        property:set属性
        message:set方法中的参数名
        -->
        <bean id="hello" class="com.zk.pojo.Hello">
            <!--value:具体的值,基本数据类型
            ref:引用spring容器中已经创建好的值 -->
            <property name="message" value="hello zk!"/>
        </bean>
    
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 调用
    @Test
    public void TestDemo01(){
        //获取spring的ApplicationContext上下文对象,即spring容器
        //参数可以传多个
        //解析bean.xml文件,生成管理相应的bean对象
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Beans.xml");
            //getBean:参数为spring配置文件中bean的id
            //这里不强转,也可以在第二个参数传入类型,类似mybatis
           //**id前添加&获取工厂
        Hello hello = applicationContext.getBean("hello", Hello.class);
        System.out.println(hello.getMessage());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 结果
    hello zk!
    
    • 1

    注意存在的问题:

    xml依赖注入arg是通过构造函数,property是通过seter方法,name属性要和实体类的属性名一致

    spring容器调用无参构造器创建队像,然后用set注入,所以实体类需要无参构造器。若没有无参构造,容器通过反射创建对象(Class对象的newInstance()方法默认调用的是无参构造)会失败

    没spring托管叶子:XML顶部的警告:配置上下文
    在这里插入图片描述


    在这里插入图片描述

    • 类单继承,接口多继承,但是由于jdk8中接口可以使用default关键字具体实现方法,所以实际上实现多个接口可能会出现类的多继承的效果
    public interface Trst {
        default void test() {
            System.out.println("方法体");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 区别就是需求变更后只需要在配置文件中改一次,不需要到处在别的类的代码中修改,改源代码需要重新发布项目,后续这些配置会放到统一的配置中心去,类似一个后台。在线修改后,运行中的项目会直接热加载,即时生效。

    改配置文件需要需要知道加载机制是热加载还是冷加载

    • 依赖注入:property利用set方法进行注入,所以实体类必须有这个属性的构造方法
    <property name="message" value="hello zk!"/>
    
    • 1
    • 若想进一步了解这个容器创建bean的实现可以浏览下ClassPathXmlApplicationContext类的源码

    本专栏下一篇:Spring IoC 使用

  • 相关阅读:
    Python实现基于深度学习的图像风格迁移
    C# Linq源码分析之Take(五)
    C#:实现交换排序算法(附完整源码)
    SpringMVC入门宝典(七)SpringMVC文件上传(下)
    C++ 11
    用jad反编译工具查看java接口相关的默认修饰符
    Taobao Proxy Purchasing System
    一篇文章带你掌握主流办公框架——SpringBoot
    【C++】STL中 vector 的模拟实现
    【UI】饿了么 el-upload如何上传到不同的路径, 根据不同情况上传指不同的接口,不同的路径
  • 原文地址:https://blog.csdn.net/weixin_42045639/article/details/125529708