IoC底层原理

举报
YuShiwen 发表于 2022/03/30 23:42:52 2022/03/30
【摘要】 前沿: 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来降低代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Inject...

前沿:

  • 控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来降低代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。IoC可以认为是一种全新的设计模式,但是理论和时间成熟相对较晚,并没有包含在GoF中。
  • Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。
    采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。 也就是说把对象创建和对象之间的调用过程,交给了Spring进行管理。

一. 底层主要用到的技术

  • xml解析
  • 工厂模式
  • 反射

现在我们开始讲解:
先看如下代码:

public class Person {
    public void eat(){
        System.out.println("吃饭!");
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
public class Student {
    private Person person = new Person();

    public void eatForStudent(){
        person.eat();
        System.out.println("喝牛奶!");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在Student类中需要用到Person,此时我们一般的做法是在Student类中new一个Person的对象,然后通过这个对象去调用其方法,但是我们是否想过,如果Person类发生的改变,比如类名发生了改变,类的路径发生了改变,假如说其他类中也创建了Person对象,如果在其他的类中也创建了Person类对象,这个时候就需要大量的改类路径或者名称,很麻烦了,这个时候我们可以用到如下的工厂模式去解决这个问题:

public class PersonFactory {
    public static Person getPerson(){
        return new Person();
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
public class Student {
    private Person person = PersonFactory.getPerson();

    public void eatForStudent(){
        person.eat();
        System.out.println("喝牛奶!");
    }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

然后在Student类中去调用getPerson方法返回Person类对象,把创建对象的过程交给工厂类PersonFactory来做,如果其他类中也都调用PersonFactory类中的getPerson方法来获取Person类对象,那么如果Person的类路径或者类名改变了,也只需要改变一处即可,也就是改变getPerson方法中的类名称或类路径。

在用了工厂模式之还是有一定的耦合度,此时我们就需要我们的IOC原理,把耦合度降低到最低,在这个过程中除了用到工厂模式外,还需要用到xml解析加上反射。

二.IOC原理过程

步骤一:xml配置文件,配置创建的对象

<bean id="person" class="iocprinciple.Person"></bean>

  
 
  • 1

步骤二:创建工厂类(在工厂模式的基础上利用xml解析加上反射来创建Person类的对象)

public class PersonFactory {
    public static Person getPerson() throws Exception {
        //Dom4j xml解析获取类的全路径
        String classPath = new ClassPathXmlApplicationContext("bean1.xml").getClassPath("person");

        //通过反射得到类的字节码文件
        Class clazz = Class.forName(classPath);

        //调用方法得到对象
        Person person = (Person)clazz.newInstance();

        return person;
    }

}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

Person类内容不变,Student变为如下:

public class Student {
    private Person person;
    
    public void eatForStudent(){

        try {
            person = PersonFactory.getPerson();
        } catch (Exception e) {
            e.printStackTrace();
        }

        person.eat();
        System.out.println("喝牛奶!");
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

用到Dom4j的xml解析类如下:

import java.io.InputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ClassPathXmlApplicationContext {
    private String configFilePath;

    public ClassPathXmlApplicationContext(String configFilePath) {
        this.configFilePath = configFilePath;
    }

    /*
     * dom4j解析
     */
    public String getClassPath(String id) throws Exception {
        String classPath = null;
        // 解析xml
        SAXReader reader = new SAXReader();
        InputStream inputStream = ClassLoader.getSystemResourceAsStream(configFilePath);
        Document document = reader.read(inputStream);
        if (document == null) {
            return null;
        }
        // 从项目根目录下读取
        Element root = document.getRootElement();

        // 获取节点资源
        List<Element> list = root.elements();
        if (list.size() <= 0) {
            return null;
        }
        for (Element element : list) {
            String idString = element.attributeValue("id");
            if (id.equals(idString)) {
                // 获取bean的class地址
                classPath = element.attributeValue("class");
                break;
            }
        }
        return classPath;
    }

}


  
 
  • 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
  • 43
  • 44
  • 45
  • 46
  • 47

这就是spring中IoC的底层原理,在之后的使用过程中,我们只需要写好spring的xml配置文件就可以啦,Spring已经为我们写好了这些关于IoC底层的代码。

文章来源: blog.csdn.net,作者:Mr.Yushiwen,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/MrYushiwen/article/details/109953263

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。