Spring IOC

11 篇文章 1 订阅
1 篇文章 1 订阅

IOC

        Inversion of Control 译为控制反转,是一种设计思想,Spring通过IOC容器来管理所有的Java对象的实例化和初始化,控制对象与对象之间的依赖关系。

由IOC管理的Java对象被称为Spring Bean,他们与通过new关键字创建出来的Java对象没有任何区别。

一个类想要使用另一个类的属性,就需要使用new关键字将后者的对象实例创建出来才能实现属性和方法的调用。即调用者控制着被调用者对象创建的控制权。

在Spring应用中,Java对象创建的控制权是掌握在IOC容器里的,大致步骤如下:

  1. 开发人员通过XML、注解、配置文件等方式将Java对象进行定义。
  2. 当Spring启动时,IOC容器会自动的根据据对象定义将对象创建并管理起来,这个由IOC容器管理的实例被称之为Spring Bean。
  3. 当需要某个Bean时,直接从IOC容器中获取即可,而不需要通过new关键字创建。

控制反转:原本调用者是主动的一方,即需要上面资源直接通过new关键字创建。但是在Spring中,IOC容器掌握着主动权,调用者成了被动的一方,被动的等待IOC容器来创建它所需要的对象。

DI

        Denpendency Injection 译为依赖注入,Martin Fowler 在 2004 年在对“控制反转”进行解释时提出的。Martin Fowler 认为“控制反转”一词很晦涩,无法让人很直接的理解“到底是哪里反转了”,因此他建议使用“依赖注入”来代替“控制反转”。
        依赖关系是一个对象需要用到另外一个对象,即该对象中存在一个属性在另一个对象。Spring在创建对象的过程中会根据依赖关系,将它依赖的对象也注册到IOC容器中。
        依赖注入本质上是Spring Bean属性注入的一种,只不过这个属性是对象的属性。

IOC工作原理

IOC底层通过工厂模式、反射、XML解析等技术来降低代码的耦合度

  1. 在配置文件中对各个对象以及他们之间的依赖关系进行配置。
  2. IOC容器作为一个工厂,Bean就是产品。
  3. Spring在启动时会加载并解析配置文件,得到对象和他们之间的依赖关系。
  4. IOC利用反射,根据类名生成相应的对象,并根据依赖关系将这个对象注入到他依赖的对象中。

Spring是怎样设计容器的?

使用 ApplicationContext,它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory 的。

BeanFactory 简单粗暴,可以理解为 HashMap:

  • Key - bean name

  • Value - bean object

但它一般只有 get, put 两个功能,所以称之为“低级容器”。

而 ApplicationContext 多了很多功能,因为它继承了多个接口,可称之为“高级容器”。在下文的搭建项目中,我们会使用它。

ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的:

  • ClassPathXmlApplicationContext - 从 class path 中加载配置文件,更常用一些;

  • FileSystemXmlApplicationContext - 从本地文件中加载配置文件,不是很常用,如果再到 Linux 环境中,还要改路径,不是很方便。

当我们点开 ClassPathXmlApplicationContext 时,发现它并不是直接继承 ApplicationContext 的,它有很多层的依赖关系,每层的子类都是对父类的补充实现。

而再往上找,发现最上层的 class 回到了 BeanFactory,所以它非常重要。

代码演示

hello接口

public interface HelloMapper {

    void sayHello();
}

hello接口实现类  ---- 业务类

public class HelloMapperImpl implements HelloMapper{

    @Override
    public void sayHello() {
        System.out.println(" something !!!");
    }
}

测试类

    @Test
    public void test(){
        HelloMapper helloMapper = new HelloMapperImpl();
        helloMapper.sayHello();
    }

执行结果

这是使用传统方式编写的代码,HelloMapperImpl 需要实现接口 HelloMapper,而测试类 test 需要依赖 HelloMapperImpl 这个业务类。所以测试类中就需要创建这个业务类的实例,然后才可以在测试类中使用。

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

    <!-- bean就是java对象实例, 即Spring创建和管理的不是类型而是实例 -->
    <!-- Spring配置文件中的bean其实应该写在Java程序代码中,这段代码通常是new一个对象实例 -->
    <bean id="hello" class="mapper.HelloMapperImpl"/>
</beans>

测试类

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        HelloMapper hello = context.getBean("hello", HelloMapper.class);
        hello.sayHello();
    }

Spring使用步骤:

  1. 找到配置文件。
  2. 加载配置文件。
  3. 解析配置文件中的bean元素,并识别id和class。
  4. 通过反射(Class.forName().newInstance())创建这个bean的实例。
  5. 将id作为key、实例作为value存放进Spring容器中。
  6. getBean取出实例
HelloMapper hello = context.getBean("hello", HelloMapper.class);

// 等价于

HelloMapper hello = class.forName("mapper.HelloMapperImpl").newInstance();

即根据配置文件 <bean> 中的 class属性值通过反射创建对象实例,并将 <bean> id 作为key,实例作为 value 保存在IOC容器中。在需要使用的时候直接从IOC容器中就可以获取到对象实例,而不需要通过new关键字的方式主动获取所依赖的对象实例,即获取对象实例的控制权反转了,不再是主动new,而是从第三方(IOC容器)中获取。

总结

        所有的类都会在Spring容器中登记,告诉Spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。
    所有的类的创建、销毁都由 Spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是Spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
    IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。
    控制反转IOC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方。
    DI(依赖注入)其实就是IOC的另外一种说法,控制的什么被反转了?就是:获得依赖对象的方式反转了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值