Spring学习总结(二):IOC的介绍和原理

一、IOC的介绍

       上一篇中介绍了IOC和AOP是Spring的核心。何为IOC?IOC(Inversion Of Control)意为控制反转,它把对象的创建、对象间的调用关系交给Spring来管理,从而达到类间降低耦合度的目的。

       IOC有两种方式,DI(Dependecy Injection)和DL(Dependency Lookup)。DI即为依赖注入,也就是我们常说的属性注入,DL则是当前软件实体主动去某个服务注册地查找依赖的哪些服务(使用不多,资料较少)。

       关于IOC、DI和DL的具体区分,可参考此博客:https://www.cnblogs.com/vince-zww/p/11498605.html

二、IOC的原理

       在IOC的底层中,用到了三种关键技术,分别是:XML文件解析;工厂模式;反射。那么有人就有疑问了,IOC的好处到底在哪?接下来,我们模拟一个实际场景来分析一下。在Web三层结构中,我们通常会用UserService去调用UserDao,从而完成用户的业务操作,传统的实现方式真的好吗?

1、传统方式

       传统方式实现如下,相信大家都能写出来,如下:

        在传统方式中,UserService和UserDao类间耦合度太高了。假设此时UserDao的路径发生变化,那么此时的UserService也要发生变化。这种牵一发而动全身的方式,大大提高了开发的难度,不利于程序的扩展。

2、工厂模式实现

       工厂模式专门定义一个类来负责创建其他类的实例,这在一定程度上降低了类间的耦合度,如下:

        这种方式降低了UserSerivce和UserDao之间的耦合,但并没有达到最低的耦合度。

3、IOC方式

       通过IOC方式,当UserDao的路径发生变化时,只需要对配置文件中bean的class属性进行修改即可。

三、IOC容器

       IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。在Spring中BeanFacotry是IOC容器的实际代表者。Spring 提供了两种不同类型的容器:ApplicationContext 和BeanFactory。

1、BeanFactory

       BeanFactory是IOC容器的基本实现,是Spring内部使用的接口,不提供给开发人员使用。在加载配置文件时不会创建对象,只有在获取对象时才创建对象。一般不建议使用BeanFactory。简单使用一下BeanFactory。

       (1)实现步骤

       1)创建HelloApp类,并定义sayHello()方法。

       2)在bean.xml配置HelloApp。

       3)进行单元测试。

       (2)实现过程

       定义HelloApp.java:

package com.yht.example1;
public class HelloApp {
    public void sayHello(){
        System.out.println("hello  Spring");
    }
}

       在bean.xml中配置:

    <bean id="helloApp" class="com.yht.example1.HelloApp"></bean>

       进行单元测试:

    @Test
    public void testBeanFactory(){
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("bean.xml"));
        HelloApp helloApp = (HelloApp) beanFactory.getBean("helloApp");
        helloApp.sayHello();
    }

       执行结果如下:

 

       注意以下两点:

       在第一步中,利用框架提供的 XmlBeanFactory() API 去生成工厂 bean 以及利用 ClassPathResource() API 去加载在路径 CLASSPATH 下可用的 bean 配置文件。XmlBeanFactory() API 负责创建并初始化所有的对象,即在配置文件中的 bean。

       在第二步中,利用第一步生成的 bean 工厂对象的 getBean() 方法得到所需要的 bean。 这个方法通过配置文件中的 bean ID 来返回一个真正的对象。一旦得到这个对象,就可以利用这个对象来调用该类中的任何方法。

2、ApplicationContext

       ApplicationContext是BeanFactory的子接口,包括 BeanFactory 容器的所有功能,在加载配置文件时就会把配置文件中的对象创建出来。

       ApplicationContext 接口的实现类:

类名 作用
FileSystemXmlApplicationContext 该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。这里的路径是文件所在的盘符路径,如:D:\spring\bean.xml.
ClassPathXmlApplicationContext 该容器从 XML 文件中加载已被定义的 bean。它不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件。
WebXmlApplicationContext 该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean


       测试如下:       修改一下上一个例子,将配置文件的路径更改到D盘的java目录下,通过FileSystemXmlApplicationContext来创建对象,并调用方法。

    @Test
    public void testFileSystemXmlApplicationContext(){
        ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\Java\\bean.xml");
        HelloApp helloApp = (HelloApp) applicationContext.getBean("helloApp");
        helloApp.sayHello();
    }

       执行结果如下:

3、BeanFactory和ApplicationContext 的对比

BeanFactory ApplicationContext
Spring内部使用的接口 BeanFactory的子接口
加载配置文件时不创建对象,对象使用时才创建 在加载配置文件时就创建对象
一般不推荐使用 推荐使用

       之所以不推荐使用BeanFactory,是因为它在对象使用时才创建。有人会有疑问:这种方式难道不好吗?值得注意的是,我们在用Spring做Web应用时,都会将消耗性能的操作放在服务器启动之时,而创建对象的操作正好是比较消耗性能的。此外,ApplicationContext 是BeanFactory的子接口,它提供了一些高级功能,包括一些面向企业应用程序的功能,而BeanFactory只提供了基本功能。

猜你喜欢

转载自blog.csdn.net/weixin_47382783/article/details/112725498