Spring中IOC(控制反转)的理解

2022-07-27,,,,

Spring中的IOC(控制反转

先不讲IOC,

我们先通过发现问题,然后使用工厂模式解决问题,最后到IOC

示例:

分析jdbc的两种注册驱动的方式,比较两种方式哪种更适合实际的开发

DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver);

Class.forName("com.mysql.cj.jdbc.Driver");

第一种方式,我们为了注册驱动,new了一个Driver实例

第二种方式,利用反射技术,通过一个字符串创建了一个实例

这个时候,如果我们的项目换了一个数据库,这时就要换一个驱动,对于这两个注册驱动的方式来看,一种需要我们更换new的对象,第二种方式,我们只是修改了字符串,如果对第二种方式再次改进,把字符串(指的就是类的全限定名)写到一个配置文件中,那么让程序读取配置文件就可以知道去创建哪个对象。如果我们需要更换数据库,就可以直接修改配置文件,从而避免了对源代码的修改

结论:在我们使用一些不需要被频繁创建的对象时,采用反射的方式创建对象显然更加合理,当我们这个对象需要更换时,就可以在不修改源代码的基础上,通过配置文件做出对应的改变

解耦的必要性

解除耦合:解除依赖关系,但是在一个程序的开发中,两个模块协同完成工作,必然会产生耦合,发生依赖关系,如果真的把两个模块的依赖关系切断了,那么也就不存在共同工作了,所以这里的解耦是让两个模块之间的耦合性降低。

实际开发中,低耦合性是最基本的要求,可以让我们开发的功能独立性提高,增加了模块的复用性,同时,降低了后期维护的成本

高内聚,低耦合

现在无处不提到“低耦合、高内聚”,它已经成为软件设计质量的标准之一。

  • 内聚标志一个模块各个元素彼此结合的紧密程度,它是信息隐藏和局部化概念的自然扩展。主要是指的功能内聚,每一个元素只完成它职责内的事情,其他的事情都交给别人来完成,这就是高内聚的元素
  • 低耦合就是模块之间的依赖关系变低,当一个模块需要被更换之后,不会牵连其他模块的更换,新换的模块可以继续和其他模块一起工作,就是一个良好的低耦合的项目

工厂模式

工厂模式使我们最长的用的一个实例化对象的模式,

我们现在使用工厂模式,自己写一个为了解除耦合关系的简单案例

创建一个持久层的Dao(模拟)

public class UserDaoImpl implements IUserDao {

    @Override
    public void save() {
        System.out.println("向数据库中添加一条用户信息");
    }
}

创建一个业务层,他需要处理业务,然后调用Dao层将数据进行持久化存储。

public class UserServiceImpl implements IUserService {
    private IUserDao userDao;
    @Override
    public void add() {
        System.out.println("处理业务,存储数据");
        userDao = (IUserDao) BeanFactory.getBean("UserDao");
        userDao.save();
    }
}

创建一个beans.xml文件,将我们的类的信息放在xml文件中

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean id="UserDao"  class="com.zxy.dao.impl.UserDaoImpl"/>
    <bean id="UserService" class="com.zxy.service.impl.UserServiceImpl"/>
</beans>

我们使用dom4j来解析xml文件(Spring也是使用dom4j来解析XML文件的)

<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>

创建一个工厂,用来创建对象,它会解析xml文件,根据配置信息创建所有的对象

public class BeanFactory {
    private static Map<String,Object> beanMap = new HashMap<>();
    static {
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml"));
            //获取根节点:beans
            Element rootElement = document.getRootElement();
            //获取根节点下的所有子节点
            List<Element> elementList = rootElement.elements();
            //遍历标签中的信息,使用利用反射创建对象,放在beanMap中
            for (Element element : elementList){
                String idValue = element.attributeValue("id");
                String classValue = element.attributeValue("class");
                Class clazz = Class.forName(classValue);
                Object obj = clazz.getDeclaredConstructor().newInstance();
                beanMap.put(idValue,obj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Object getBean(String id){
        return beanMap.get(id);
    }
}

运行测试类:

    @Test
    public void test1(){
        IUserService userService= (IUserService) BeanFactory.getBean("UserService");
        userService.add();
    }

体会上面简单的例子,其实Spring在实现IOC时,也是使用的这种做法

IOC

IOC(Inversion of Control)控制反转:是一种设计思想,是一个重要的面向对象编程的法则,使用这种思想可以让我们设计出低耦合、更加优良的程序。

IOC是Spring中的核心,它主要的特点就是:调用类中的方法不是通过new它的对象来实现,而是通过Spring配置来创建对象,然后交给IOC容器来管理我们的对象,使用时去找IOC容器要,根本就不用去管我们需要的这个对象时怎么创建的、什么时候被销毁。

这样一来,类和类之间的关系就变弱了,因为我们没有在一个类中new另一个对象,对象之间的调用、联系都是通过这个IOC容器来获取的,使每一个对象都相对比较独立

程序中对象相互合作,发生耦合的情况:

使用IOC解耦后:

解释一下控制反转

  • 原本我们自己手动控制对象(创建和销毁,对象的生命周期
  • 变成了现在交给IOC容器控制对象(创建和销毁)、我们使用时只需要去容器中获取即可

Spring IOC底层运用的技术包括xml配置文件、dom4j解析xml、工厂设计模式、反射,这四种技术

下一篇Spring IOC的使用 ※

本文地址:https://blog.csdn.net/zxy144/article/details/110250205

《Spring中IOC(控制反转)的理解.doc》

下载本文的Word格式文档,以方便收藏与打印。