前面的是没有依赖时如何创建对象,现在是有依赖时如何创建对象。

IOC的作用:降低程序间的依赖关系。但是不是消除依赖关系,所以程序间必然有一些依赖关系,依赖关系的管理以后都交给spring来维护,什么是依赖关系呢?就是在当前类中需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中告诉spring我们用哪个类的对象

能注入的数据有三类:

1、 基本类型的包装类和String

2、 其他Bean类型(在配置文件中或注解配置过的Bean,即spring容器中)

3、 集合类型

依赖注入的方式有三种:

1、 使用构造函数提供

2、 使用set方法提供

3、 使用注解提供

一、依赖作为参数使用构造函数注入

将注解@autowired加在有参构造函数上

service

@Service
public class UnitInfoService {
    private UnitInfoMapper unitInfoMapper;
    @Autowired
    public UnitInfoService(UnitInfoMapper unitInfoMapper){
        this.unitInfoMapper = unitInfoMapper;
    }
}

controller

@RestController
public class UnitInfoController {
    private UnitInfoService unitInfoService;
    @Autowired
    public UnitInfoController(UnitInfoService unitInfoService) {
        this.unitInfoService = unitInfoService;
    }
}

当构造方法只有一个,且该构造方法是有参构造时,@Autowired注解可以省略。

@Service
public class UnitInfoService {
    private UnitInfoMapper unitInfoMapper;
    public UnitInfoService(UnitInfoMapper unitInfoMapper){
        this.unitInfoMapper = unitInfoMapper;
    }
}

步骤:

1、 在类中定义可注入的变量

先来演示类型为基本类型的包装类、字符串,Date为其他Bean类型

在你不提供任何构造函数的情况下,系统会赠送一个默认构造函数。现在已经定义了一个满参构造函数,所以没有默认构造函数了,所以使用默认构造函数创建Bean对象会报错,应该用满参构造函数创建Bean对象。

2、使用constructor-arg标签,标签出现的位置是bean标签的内部

Constructor-arg标签中的属性:

1)、type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型

这样只能把test变量注入给带参构造函数中String类型的参数,但是如果构造函数的参数中有两个String类型的参数就不知道给哪个注入了。故type属性不能独立实现注入的功能

2)、index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始

3)、name:用于指定给构造函数中指定名称的参数赋值

常用的以上三个用于指定给构造函数中哪个参数赋值,常用name属性

4)、value:用于提供基本类型的包装类和String类型的数据

5)、ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象

Age是Integer类型,而value=“18”,在xml中写的时候,value值都是字符串。Spring能把这些类型进行转换的。而birthday是Date类型,而value=“1970-01-01”,并不是日期类型,而只是普通的字符串,你用字符串给对象赋值,spring是无法转换的。我们可以配置一个日期对象,然后用ref属性引用关联的Bean对象。

3、测试:获取Bean对象,调用方法

结果:

优势:在创建Bean对象时,注入数据是必须的操作,否则对象无法创建成功。
弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。如果我们在bean.xml中少提供任何一个参数,对象都创建不出来,除非你在类中加很多重载的构造函数。

在实际开发中,除了必须采用这种方式之外,其他情况一般不用构造函数注入的方式来创建对象

二、依赖作为参数使用set方法注入

set注入是将注解autowired添加到该属性的set方法上

service

 

@Service
public class UnitInfoService {
   private UnitInfoMapper unitInfoMapper;
    @Autowired
    public void setUnitInfoMapper(UnitInfoMapper unitInfoMapper){
        this.unitInfoMapper = unitInfoMapper;
    }
}

controller

@RestController
public class UnitInfoController {
    private UnitInfoService unitInfoService;

    @Autowired
    public void setUserService(UnitInfoService unitInfoService) {
        this.unitInfoService = unitInfoService;
    }
}

步骤:

1、在类中添加Set方法:(注意:注入只需要set方法,不需要get方法)

由于没有提供任何构造函数,系统会赠送一个默认构造函数

2、使用property标签,标签出现的位置是bean标签的内部

 

property标签的属性
1、name:用于指定注入时所调用的set方法名称,即属性,而不是成员变量。不过一般情况属性和成员变量相同
2、value:用于提供基本类型和String类型的数据
3、ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象

3、测试:获取Bean对象,调用方法

 结果:

优势:创建对象时没有明确的限制,可以直接使用默认构造函数。解决了构造函数注入的弊端问题。
弊端:如果有某个成员必须有值,则set方法无法保证一定注入,即获取对象时有可能set方法没有执行。因为创建对象时没有参数的限制,而是调用默认构造函数,有可能调用默认构造函数用,这个时候可能数据就没有值。

与使用构造函数注入相比,set方法注入更常用。

三、集合类型的注入

包括数组、List集合、Set集合、Map集合、Properties属性集

1、在类中添加数组、List集合、Set集合、Map集合、Properties属性集类型的成员变量,并生成set方法以注入依赖。

2、property标签的value属性和ref属性都注入不了集合类型,这时使用property的子标签array、list、set、map、props。

Props标签的属性只有key一个,key的值是标签体中的内容。

用于给List结构集合注入的标签有list、array、set

用于给Map结构集合注入的标签有Map、props

结构相同,标签可以互换,即list、array、set三个标签可以互换,Map和props标签可以互换。

 

依赖注入方式选择

1. 强制依赖使用构造器进行,使用 setter 注入有概率不进行注入导致 null 对象出现

2. 可选依赖使用 setter 注入进行,灵活性强

3. Spring 框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨

4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用 setter 注入完成可选依赖的注入

5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供 setter 方法就必须使用构造器注入 6. 自己开发的模块推荐使用 setter 注入

 

posted on 2024-07-10 18:04  周文豪  阅读(93)  评论(0编辑  收藏  举报