Spring中IOC的理解(通俗易懂版)



1.IOC提出背景

  • 代码书写现状:耦合度太高,我们修改一处代码,往往要修改很多出相关联的代码。

举例如下:当我们在数据层中不满足BookDaoImpl2中提供的方法了,我们写了新的实现类BookImpl,那么当业务层想要调用数据层中的实现方法的时候,我们就要修改 new 的对象。那么引发问题 我们该一处代码,就要修改与其相关联的代码。
。

  • 解决方法:我们在创建对象的时候,不自己创建而是由外部提供对象

  • 引出IOC(控制反转)
    对象的创建权由程序转移到外部,这种思想叫做控制反转。

2:IOC的核心概念

  • 使用对象时候由主动new对象转换成由外部提供对象,此过程中对象的创建权由程序转移到外部,这种思想叫做控制反转
  • Spring技术对此提供的实现
    • Spring提供了一个容器,称为IOC容器,用来充当IOC思想中的外部
    • IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IOC容器中统称为Bean

3:IOC的实现方式

  • DI-依赖注入
    在容器中建立bean与bean之间的依赖关系的整个过程叫做依赖注入

下方当中的业务层中代码想要正常运行还需要Book bookDao的实现,那么的话IOC把这种依赖关系也提供给业务层,这个过程叫依赖注入。那么这个注入指的就是属性的注入
在这里插入图片描述

4:IOC的入门案例

(1):思路分析

  • IOC管理什么(bean对象)
  • 如何告知IOC去管理bean对象 —通过配置文件
  • 被管理的对象交给IOC容器,如何获取IOC容器?(接口)
  • IOC容器得到后,如何获取bean?

(2):代码解析

  • IOC管理的对象
    这里的话我们还未完成依赖注入,所以还是new了一个mapper的对象
public class bookServiceImp implements bookService {

   bookMapper mapper = new bookMapperImp();

    @Override
    public void add2() {
        mapper.add();
    }
}
  • 告知IOC去管理bean(通过配置文件)
 	<!-- id:相当于类别名-->
    <!-- class:引入的类-->
    <bean id = "bookMapperImp" class="com.wyi.mapper.Imp.bookMapperImp"/>
    <bean id = "bookServiceImp" class="com.wyi.service.Imp.bookServiceImp"/>
  • 获取IOC容器

ApplicationContext是个接口,所以需要用其实现类CPX

 ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
  • 获取bean
    getBean的参数就是我们在配置文件当中的id;
 bookServiceImp imp = (bookServiceImp) context.getBean("bookServiceImp");

5:DI入门案例

(1):思路分析

  • 基于IOC管理bean。
  • 上方的service中new 的mapper对象是否保留(否)。
  • Service需要的mapper对象如何进入Service中 (通过提供方法)。
  • Service和mapper之间该如何联系。

(2):代码解析

  • Service需要的mapper对象如何进入Service中 (通过提供方法)

public class bookServiceImp implements bookService {

   bookMapper mapper;

    @Override
    public void add2() {
        mapper.add();
    }
    //提供set方法
    public void setMapper(bookMapper mapper) {
        this.mapper = mapper;
    }
}
  • Service和mapper之间的联系
   <!-- id:相当于类别名-->
    <!-- class:引入的类-->

    <bean id = "bookMapperImp" class="com.wyi.mapper.Imp.bookMapperImp"/>

    <bean id = "bookServiceImp" class="com.wyi.service.Imp.bookServiceImp">

<!--        property:表示的是配置当前bean的属性-->
<!--        name:表示当前bean的属性名称-->
<!--        ref:参照哪一个bean
			ref:bean对象的属性是引用类型,value:bean对象的属性是基本类型		-->
        <property name="mapper" ref="bookMapperImp"/>
    </bean>
  • 那么ioc如何调用set方法呢?
    这个时候它就会通过反射来创建对象
    调用的是无参构造方法,就算构造器私有也可以调用
    然后读取到property标签中对应的属性值
    比如说,读取到标签的name属性值为mapper,参照bookMapperImp类 (如果属性是不是对象的话 那么就是 value)
    这个时候,IOC就会调用对应的set方法为这个属性赋值(将上方读取到的 属性值 set(bookMapperImp) 进去,为 BookServiceImp提供mapper对象)
    如果我们写的实体类中没有提供对应的set方法,那么就会报错。

6:DI依赖注入的方式

(1):前言

所谓注入也就是属性的注入,我们根据bean.xml中bean对象中属性的添加方式 对应不同依赖注入方式,在某个bean中其可能需要用到其他实体类作为属性,那么此时也不用自己new,IOC容器给你提供,那么如何提供呢?那就是这个bean你得给IOC容器一个入口 即 set方法 或者构造器方法

(2):Set方式注入

  • bean当中属性的添加
    这里属性的添加方式是 property
 <bean id = "bookServiceImp" class="com.wyi.service.Imp.bookServiceImp">
        <property name="mapper" ref="bookMapperImp"/>
    </bean>
  • IoC如何注入这个属性呢
    我们先通过获取到的IOC容器,然后再通过IOC容器获取到Bean,然后底层是通过反射创建这个bean对象,然后这个bean当中可能存在一些依赖关系,那么的话这个时候IOC容器会调用set方法对这些属性进行注入。
 public void setMapper(bookMapper mapper) {
        this.mapper = mapper;
    }

(3):构造器注入

  • bean.xml配置文件
    属性的添加方式是 constructor
    <bean id = "bookServiceImp" class="com.wyi.service.Imp.bookServiceImp">
    	//这里的name是我们构造方法中的参数名
        <constructor-arg name = "mapper" ref="bookMapperImp"/>
    </bean>
  • IOC如何注入这个属性呢?
    通过构造器注入这个属性,我们配置文件中将mapper这个属性的添加方式提供了,那么接下来就是IOC容器调用构造方法将bean.xml文件中的属性注入到bookServiceImp
public class bookServiceImp implements bookService {
	private bookMapper mapper;
   public bookServiceImp(bookMapper mapper) {
        this.mapper = mapper;
    }
 }

(4):依赖的自动装配

  • 概念:IOC容器根据bean所依赖的资源在容器中自动查找 并注入到bean的过程叫做 自动装配

  • bean.xml 那么这个里头的话 我们就不要再写 property 因为我们是自动查找依赖 一般使用的是按类型

    <bean id = "bookMapperImp" class="com.wyi.mapper.Imp.bookMapperImp"/>
    <bean id = "bookServiceImp" class="com.wyi.service.Imp.bookServiceImp" autowire="byType"/>
  • bean中
    也是需要为IOC中提供一个接口来将 这个属性注入进去 这个接口是set方法
  private bookMapper mapper;

    @Override
    public void add2() {
        mapper.add();
    }

    public void setMapper(bookMapper mapper) {
        this.mapper = mapper;
    }
  • 自动装配注意事项
    自动装配用于引用类型依赖注入,不能对简单类型进行操作
    使用按类型装配时(byType)必须保障容器中相同类型的bean唯一,推荐使用
    使用按名称装配时(byName)必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用
    自动装配优先级低于setter注入与构造器注入,同时出现时自动装配配置失效

7:注解开发模式的依赖注入

(1):前言介绍

我们以前是需要用bean.xml,在其中我们需要写配置bean,那么现在我们改用注解了,想要添加那个bean对象,就在那个类上加上注解。

  • @Component
    @Component的衍生注解(衍生的注解跟@Component注解作用相同)
  • @Service
  • @Controller
  • @Repository

(2):注解模式的依赖注入(单指自动装配)

这里我们只需要在相关联的bean上添加注解@Autowired 那么IOC容器就会扫描容器中的bean,(被扫描的bean就是用@component注解或者衍生注解修饰的bean)

  • 40
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天向上的菜鸡杰!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值