Spring依赖注入DI的方式、类型、作用

2024-01-08 10:09:29

借鉴:https://blog.csdn.net/u013749113/article/details/133383259
https://blog.csdn.net/u010781073/article/details/45771579
https://blog.csdn.net/qq_53317005/article/details/130447022

一:Spring依赖注入DI的方式

1、Set方式注入:
这是最简单的注入方式,假设有一个UserService,需要在UserService中实例一个UserDAO对象
那么就可以在UserService类中定义一个private的UserDAO成员变量,然后创建UserDAO的set方法(这是IOC注入的入口)

package com.services.UserService;
 
public class UserService {
 
    private UserDAO userDAO;
 
    public void setUserDAO(UserDAO userDAO){
        this.userDAO = userDAO;
    }
}

随后编写applicationContext.xml文件

 <bean id="userDAO1" class="com.dao.UserDAO"></bean>
 <bean id="UserService" class="com.services.UserService">
     <!--  此处name的值就是UserService中的userDAO -->
     <property name="userDAO" ref="userDAO1"></property>
 </bean>

2、构造器注入:
这种方式的注入是指带有参数的构造函数的注入。注意下面的示例:我在UserService中创建两个成员变量UserDAO和User,但是并不创建set方法,所以这里就不能支持第一中的set注入,此处的注入是在UserService的构造函数中实现的,即就是在创建UserService时就要将UserDAO和User两个参数传进来

package com.service.UserService

public class UserService{

     private UserDAO userDAO;
     private User user;
     
     public UserService(UserDAO userDAO,User user){
         this.userDAO = userDAO;
         this.user = user;
     }
}

applicationContext.xml文件中同样不使用第一种property的形式,而是使用标签

<bean id="UserService" class="com.services.UserService">
    <!-- 创建构造器注入,如果带有参数的构造方法则需添加此配置 -->
    <constructor-arg  ref="userDAO"></constructor-arg>
    <constructor-arg  ref="user"></constructor-arg>
</bean>
<bean id="userDAO" class="com.dao.UserDAO"></bean>
<bean id="user" class="com.bean.User"></bean>

解决构造函数参数的不确定性
你可能会遇到构造方法传入的两个参数是相同的类型,为了分清楚哪个值对应哪个参数则需进行一些小处理,设置index的值,就是参数的位置

<bean id="UserService" class="com.services.UserService">
    <!-- 创建构造器注入,如果带有参数的构造方法则需添加此配置 -->
    <constructor-arg  index="0" ref="userDAO"></constructor-arg>
    <constructor-arg  index="1" ref="user"></constructor-arg>
</bean>

另一种设置参数类型:

<constructor-arg  type="java.lang.string" ref=""></constructor-arg>

3、注解方式注入:
Spring2.5提供了基于注解的配置,我们可以通过注解的方式来实现注入,使用@AutoWired和@Resource注解方式来实现注入

@AutoWired和@Resource区别:
@Resource默认是按照"名称"来装配的,只有找不到与名称匹配的bean才会按照类型来装配注入;
@Autowired默认是按照"类型"装配注入的,如果想按照名称来转配注入,则需要结合"@Qualifier"一起使用;
@Resource注解是又J2EE提供,而@Autowired是由Spring提供,故减少系统对spring的依赖建议使用@Resource的方式;
@Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上
使用注解的方式步骤如下:

(1)添加jar包:依赖的jar包: common-annotations.jar
(2)在applicationContext.xml文件中添加如下代码:
配置文件中加入命名空间
在Beans中添加:

xmlns:context="Index of /schema/context">
 <!-- 打开可以使用注解方式注入对象 -->
<context:annotation-config/>

到这里配置就完成了。

package com.service.impl.UserService;
import com.services.UserServiceImpl;

public class UserServiceImpl implements UserService{
    @Resource(name="userDAO")
    private UserDAO userDAO;
}
<bean id="UserServiceImpl" class="com.service.impl.UserService"></bean>
<bean id="UserDAO" class="com.dao.UserDAO"></bean>

4、通过自动扫描+注解方式注入:
Spring2.5引入了自动扫描机制,它可在classpath路径下寻找标注了
@Service (用于标注业务层组件)、
@Controller(用于标注控制层组件、
@Repository(用于标注数据访问层即Dao组件)、
@Component(泛指组件)
的类并把这些类纳入进Spring容器中管理,它的作用和在Spring文件中编写Bean节点一样

注意:这些注解是添加在Java类上的,而注解注入(第三种方式)的注解是添加在属性或方法上的;
1首先引入xmlns:content=" Index of /schema/context" 命名空间
2打开扫描 <context:component-scan base-package=“com.packagename” />
说明:如果引入了 <context:component-scan />标签就可以不用引入第3种方式中的context:annotation-config/

二:Spring依赖注入的类型

在这里插入图片描述
准备注入属性的类 :

package com.example.service;
 
import com.example.dao.StudentDao;
import com.example.pojo.Student;
 
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
 
public class StudentService {
    // service依赖dao,手动注入属性值,即手动维护依赖关系
    //private StudentDao studentDao;
 
    // bean属性
    private StudentDao studentDao;
    // 字符串类型
    private String name;
    // 基本数据类型
    private int count;
    // 字符串List集合
    private List<String> students1;
    // 对象类型List集合
    private List<Student> nameList;
    // 字符串类型Set集合
    private Set<String> students2;
    // 字符串类型Map集合
    private Map<String, String> students3;
    // 对象类型map集合
    private Map<String,Student> studentMap;
    // Properties类型
    private Properties properties;
 
    public StudentService(){}
 
    public StudentService(StudentDao studentDao){
        this.studentDao = studentDao;
    }
 
    public Student findStudentById(int id){
        return studentDao.findById(id);
    }
 
    public void setStudentDao(StudentDao studentDao){
        this.studentDao = studentDao;
    }
 
    public StudentDao getStudentDao() {
        return studentDao;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getCount() {
        return count;
    }
 
    public void setCount(int count) {
        this.count = count;
    }
 
    public List<String> getStudents1() {
        return students1;
    }
 
    public void setStudents1(List<String> students1) {
        this.students1 = students1;
    }
 
    public Set<String> getStudents2() {
        return students2;
    }
 
    public void setStudents2(Set<String> students2) {
        this.students2 = students2;
    }
 
    public Map<String, String> getNames2() {
        return students3;
    }
 
    public void setNames2(Map<String, Student> names2) {
        this.studentMap = names2;
    }
 
    public Map<String, String> getStudents3() {
        return students3;
    }
 
    public void setStudents3(Map<String, String> students3) {
        this.students3 = students3;
    }
 
    public Properties getProperties() {
        return properties;
    }
 
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
 
    public List<Student> getNameList() {
        return nameList;
    }
 
    public void setNameList(List<Student> nameList) {
        this.nameList = nameList;
    }
 
    @Override
    public String toString() {
        return "StudentService[ " +
                "studentDao=" + studentDao +
                ", name='" + name + '\'' +
                ", count=" + count +
                ", students1=" + students1 +
                ", nameList=" + nameList +
                ", students2=" + students2 +
                ", students3=" + students3 +
                ", studentMap=" + studentMap +
                ", properties=" + properties +
                " ]";
    }
}

准备测试方法

// 测试注入类型
 @Test
 public void t7(){
     ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
     StudentService service = (StudentService) ac.getBean("studentService");
     System.out.println(service);
 }

1. 注入bean类型

<!-- 注入bean类型 -->
<bean id="studentDao" class="com.example.dao.StudentDaoImpl1"/>
<!-- 写法1 -->
<bean id="studentService" class="com.example.service.StudentService">
    <property name="studentDao" ref="studentDao"/>
</bean>
<!-- 写法2 -->
<!--<bean id="studentService" class="com.example.service.StudentService">
    <property name="studentDao">
        <ref bean="studentDao"/>
    </property>
</bean>-->

2. 注入基本数据类型

<!-- 注入基本数据类型 -->
<!-- 写法一 name:属性名 value:属性值 -->
<property name="name" value="程序员"/>
<!-- 写法二 name:属性名 value:属性值-->
<property name="count">
    <value>10</value>
</property>

3. 注入List集合

 <!-- 注入List集合 -->
 <!-- 简单的数据类型List集合 name:属性名 -->
 <property name="students1" >
     <list>
         <value>上海</value>
         <value>广州</value>
     </list>
 </property>
 <!-- 对象类型的List集合 name:属性名 -->
 <property name="nameList">
     <list>
         <bean class="com.example.pojo.Student">
             <property name="id" value="1"/>
             <property name="name" value="几何心凉"/>
             <property name="address" value="北京"/>
         </bean>
         <bean class="com.example.pojo.Student">
             <property name="id" value="2"/>
             <property name="name" value="哈士奇"/>
             <property name="address" value="上海"/>
         </bean>
     </list>
 </property>

4. 注入Set集合

<!-- 注入Set集合 -->
<property name="students2">
    <set>
        <value>深圳</value>
        <value>北京</value>
    </set>
</property>

5. 注入Map集合

<!-- 注入Map集合 -->
<property name="students3">
    <map>
        <entry key="哈士奇" value="上海"/>
        <entry key="几何心凉" value="北京"/>
    </map>
</property>
<!-- 注入对象类型map类型 -->
<property name="names2">
    <map>
        <entry key="student1" value-ref="s1"/>
        <entry key="student2" value-ref="s2"/>
    </map>
</property>
<bean id="s1" class="com.example.pojo.Student">
    <property name="id" value="1"/>
    <property name="name" value="几何心凉"/>
    <property name="address" value="北京"/>
</bean>
<bean id="s2" class="com.example.pojo.Student">
    <property name="id" value="2"/>
    <property name="name" value="哈士奇"/>
    <property name="address" value="上海"/>
</bean>

6. 注入Properties对象

<!-- 注入properties -->
<property name="properties">
    <props>
        <prop key="配置1">值1</prop>
        <prop key="配置2">值2</prop>
    </props>
</property>

运行测试方法测试一下

在这里插入图片描述

三:Spring依赖注入DI的作用

1. 解耦合(Decoupling)
依赖注入有助于减少对象之间的紧密耦合。在传统的编码方式中,对象需要自己创建它所依赖的对象,这会导致高度耦合的代码。而使用DI,对象不需要知道如何创建其依赖对象,从而降低了对象之间的耦合度。

2. 可测试性(Testability)
DI使单元测试变得更加容易。通过将依赖注入到对象中,测试可以使用模拟对象或存根来代替真实的依赖对象,从而更容易进行单元测试。这可以提高代码的质量,减少bug的产生。

3. 可维护性(Maintainability)
DI提高了代码的可维护性。当应用程序需要更改依赖关系时,只需更改配置而不是修改源代码。这样可以减少因依赖变化而导致的代码修改,提高了代码的稳定性。

4. 可读性(Readability)
DI使代码更易于阅读和理解。通过查看对象的构造函数或setter方法,开发人员可以清晰地了解它所依赖的对象。这提高了代码的可读性,并使其更具可维护性。

5. 可扩展性(Scalability)
DI有助于提高应用程序的可扩展性。通过使用接口和抽象类来定义依赖关系,可以轻松地替换现有的依赖实现,以满足新的需求或支持新的功能。

文章来源:https://blog.csdn.net/qq_43185254/article/details/135389716
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。