3、Spring的DI依赖注入


一、DI介绍

1、DI介绍

  • 依赖注入,应用程序运行依赖的资源由Spring为其提供,资源进入应用程序的方式称为注入。
  • Spring容器管理容器中Bean之间的依赖关系,Spring使用一种被称为“依赖注入”的方式来管理Bean之间的依赖关系。
  • 使用依赖注入,不仅可以为Bean注入普通的属性值,还可以注入其他Bean的引用。依赖注入是一种优秀的解耦方式,其可以让Bean以配置文件组织在一起,而不是以硬编码的方式耦合在一起。

2、依赖注入

依赖注入: Dependency Injection。它是 spring 框架核心 ioc 的具体实现。

3、为什要依赖注入

直接用对象,不需要去new对象。所谓的注入就是创建对象的过程而已。

  • 传统的代码,每个对象负责管理与自己需要依赖的对象,导致如果需要切换依赖对象的实现类时,需要修改多处地方。同时,过度耦合也使得对象难以进行单元测试。

  • 依赖注入把对象的创造交给外部去管理,很好的解决了代码紧耦合(tight couple)的问题,是一种让代码实现松耦合(loose couple)的机制。

  • 例如:我们控制层调用业务层需要在控制层创建业务层的对象,之前我们需要Person p = new Person;现在不需要我们自己去new person,直接交给spring去创建,我可以直接拿过来用。

Spring 支持的注入方式共有四种: set 注入、构造器注入、静态工厂注入、实例化工厂注入。

4、IOC与DI之间的关系

IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度。其基本思想是:借助于“第三方”实现具有依赖关系的对象之间的解耦。

DI(Dependence Injection 依赖注入):将实例变量传入到一个对象中去(Dependency injection means giving an object its instance variables)。

  • 控制反转是一种思想
  • 依赖注入是一种设计模式
  • IoC框架使用依赖注入作为实现控制反转的方式

说人话:就是DI与IOC相辅相成,相互包含。不能说成DI就是IOC,这两个本质区别是:IOC是思想,DI设计模式。

二、Spring的依赖注入方式

1、Set注入

1、set注入介绍

思考:调用某个类的方法,你是怎么操作的?

答:我通过该类的构造器创建对象,通过对象去调用方法。

看图说话:

方式一与方式二对比:

  • 方式二没有主动的去实例对象,而是通过带参数的方法传递过来UserDao对象,从而实现UserService对UserDao的依赖.

  实际上创建对象是交给Spring容器来创建的

  • 属性字段需要提供set方法。并且还需要通过修改spring的配置文件,进行相关的注入信息配置。

2、Set注入标签介绍

名称:property

类型:标签

归属:bean标签

作用:使用set方法的形式为bean提供资源

格式:
    
     
    
基本属性:

 
    name:对应bean中的属性名,要求该属性必须提供可访问的set方法(严格规范为此名称是set方法对应名称)

    value:设定非引用类型属性对应的值,不能与ref同时使用

    ref:设定引用类型属性对应bean的id ,不能与value同时使用

    注意:一个bean可以有多个property标签,属性字段需要提供set方法

3、测试Set注入方式创建对象

  1. 在UserServiceImpl创建UserDao的变量,并在UserServiceImpl变量提供Set方法。
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao){

        this.userDao = userDao;

    }

    @Override
    public void saveUser() {
        System.out.println("service层通过注入的方式调用dao层,成功啦!");
        userDao.saveUser();
    }

  1. 接口类UserService
public interface UserService {
    void saveUser();
}
  1. dao层方法
public class UserDao {

    public void saveUser(){
        System.out.println("我是dao层");
    }
}

4.配置文件配置

<?xml version="1.0" encoding="UTF-8"?>


        
                
                
        

        
        

  1. 测试类
public class UserController {
    public static void main(String[] args) {

        //获取Spring上下文环境 (加载配置文件)
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");

        /*
              通过getBean方法得到Spring容器中实例化好的Bean对象 (实例化Bean对象)
              userService代表的是配置文件中bean标签的id属性值(id标识唯一的bean)
         */
        UserService userService = (UserService) context.getBean("userService");
        userService.saveUser();
    }
}

6.测试结果

程序没有报错,并正确输出我们要打印的东西

2、构造方法注入

1、构造器注入标签介绍

名称:constructor-arg

类型:标签

归属:bean标签

作用:使用构造方法的形式为bean提供资源,兼容早期遗留系统的升级工作

格式:
    
     
    
    
基本属性:
  
 
 ref:设定引用类型构造方法参数对应bean的id ,不能与value同时使用

 type :设定构造方法参数的类型,用于按类型匹配参数或进行类型校验

 index :设定构造方法参数的位置,用于按位置匹配参数,参数index值从0开始计数

 注意:一个bean可以有多个constructor-arg标签

2、构造注入测试案例

  1. 在UserServiceImpl创建UserDao的变量,并在UserServiceImpl变量提供构造方法。
public class UserServiceImpl implements UserService {

    private UserDao userDao;
    private String name;
    private int age;
    
    //根据构造器进行注入
    public UserServiceImpl(UserDao userDao, String name, int age) {
        this.userDao = userDao;
        this.name = name;
        this.age = age;
    }
    
    
    @Override
    public void saveUser() {
        System.out.println("name="+name);
        System.out.println("age="+age);
        userDao.saveUser();
    }

    public void destroy(){
        System.out.println("bean销毁");
    }
}
  1. 修改配置文件
<?xml version="1.0" encoding="UTF-8"?>


   
    
        
        
        
        

    

    

3. 其它代码与set注入代码相同

  1. 测试结果

  1. 构造标签的属性
//根据构造器进行注入
    public UserServiceImpl(UserDao userDao, String name, int age) {
        this.userDao = userDao;
        this.name = name;
        this.age = age;
    }

带name属性


        
        
        
        


不带name属性,顺序要按照构造方法的参数类型进行设置


        
        
        
        


index0表示第一个参数,index1表示第二个参数,以此类推


        
        
        
        

3、集合注入

1、集合类型标签介绍

名称:array,list,set,map,props

类型:标签

归属:property标签 或 constructor-arg标签

作用:注入集合数据类型属性

格式:
    
     
    

1、集合类型数据注入——list(重点)


   
       why
       66666
   

(2)集合类型数据注入——props(重点)


   
       javaxxf
       666666
   

(3)集合类型数据注入——array (了解)


   
       123456
       66666
   

(4)集合类型数据注入——set(了解)


    
        javaxxf
        66666
    

(5)集合类型数据注入——map(了解)


   
       
       
   

   
       
       
   

2、测试集合注入

  1. 创建集合并提供set方法
package com.why.service.impl;

import com.why.service.UserService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;

public class UserServiceImpl implements UserService {

    private ArrayList arrayList;
    private Properties properties;
    private int[] arr;
    private HashSet hset;
    private HashMap hmap;

    public void setArrayList(ArrayList arrayList) {
        this.arrayList = arrayList;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }

    public void setArr(int[] arr) {
        this.arr = arr;
    }

    public void setHset(HashSet hset) {
        this.hset = hset;
    }

    public void setHmap(HashMap hmap) {
        this.hmap = hmap;
    }

    @Override
    public void saveUser() {
        System.out.println("ArrayList"+arrayList);
        System.out.println("Properties"+properties);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("HashSet"+hset);
        System.out.println("HashMap"+hmap);
    }
}
  1. 配置文件
<?xml version="1.0" encoding="UTF-8"?>



    
        
        
            
                list1
                list2
                list3
            
        
        
        
            
                java
                java
                java
            
        
        
        
            
                11
                12
                13
            
        
        
        
            
                
                
            
        
        
        
            
                hset1
                hset2
                hset3
            
        
    


  1. 运行结果

三、参考资料

控制反转(IoC)与依赖注入(DI)