您现在的位置是:首页 >技术交流 >Spring:依赖注入的方式(setter注入、构造器注入、自动装配、集合注入)网站首页技术交流

Spring:依赖注入的方式(setter注入、构造器注入、自动装配、集合注入)

坚持不懈的大白 2023-07-10 08:00:02
简介Spring:依赖注入的方式(setter注入、构造器注入、自动装配、集合注入)

依赖注入的方式有setter注入、构造器注入、自动装配、集合注入

首先,Maven项目pom.xml依赖包如下:
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
    </dependencies>
</project>

【注】:上述除spring依赖包之外其他三个依赖包用于测试使用。

1. setter注入

先说明一下,这里有的文件为Book2Dao(接口)、Book2DaoImpl(Book2Dao接口实现类)、Book2Service(接口)、Book2ServiceImpl(Book2Service即可实现类)、Test2(用于测试)。示例在Book2ServiceImpl类中使用Book2Dao的方法save,如下:

Book2Dao

package com.bh.dao;
public interface Book2Dao {
    void save();
}

Book2DaoImpl

package com.bh.dao.Impl;

import com.bh.dao.Book2Dao;
public class Book2DaoImpl implements Book2Dao {
    public void save() {
        System.out.println(" Book2DaoImpl 已保存数据!");
    }
}

Book2Service

package com.bh.service;

public interface Book2Service {
    void save();
}

Book2ServiceImpl

package com.bh.service.Impl;

import com.bh.dao.Book2Dao;
import com.bh.service.Book2Service;

public class Book2ServiceImpl implements Book2Service {
    private Book2Dao book2Dao;
    public void setBook2Dao(Book2Dao book2Dao) {
        this.book2Dao = book2Dao;
    }
    public void save() {
        book2Dao.save();
    }
}

applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation=
               "http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd

                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd

">

<!--    开启context的命名空间  -->
     <bean id="book2Dao" class="com.bh.dao.Impl.Book2DaoImpl"/>

    <bean id="book2Service" class="com.bh.service.Impl.Book2ServiceImpl">
        <property name="book2Dao" ref="book2Dao"/>
    </bean>
</beans>

【注】:这个xml文件是开启了context的命名空间的,用于后续操作。
Test2

package com.bh;

import com.bh.service.Book2Service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test2 {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Book2Service book2Service = ctx.getBean("book2Service", Book2Service.class);
        book2Service.save();
    }
}

运行结果为:
请添加图片描述

这种方式如果在Book2ServiceImpl类中引入多个其他类的依赖时,在配置文件applicationContext.xml上就需要写上对应的property标签,并且一旦Java类上这些引入的依赖变量名称进行修改,对应的配置文件bean标签里的property标签也要进行相应的修改,显得很繁琐,有没有简便的方法呢?有的,那就是使用自动装配
自动装配

只需要修改一下applicationContext.xml配置文件即可。

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation=
               "http://www.springframework.org/schema/beans
                http://www.springframework.org/schema/beans/spring-beans.xsd

                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context.xsd

">
<!--    开启context的命名空间  -->
     <bean id="book2Dao" class="com.bh.dao.Impl.Book2DaoImpl"/>

    <bean id="book2Service" class="com.bh.service.Impl.Book2ServiceImpl" autowire="byType"/>
</beans>

运行结果和上述一样。
如果在上述applicationContext.xml定义了两个Book2DaoImpl类型相同的bean,则会报错,如下:
请添加图片描述

运行结果:
请添加图片描述
请添加图片描述
从报错信息上分析,是因为我定义了两个class类型相同的bean,而使用的自动装配方式是按类型(byType)进行装配的,我可以修改一下自动装配类型,使用byName按名称,这样就没有问题了,如下:
请添加图片描述
这样修改之后,就能正常运行出结果了。但是使用按名称进行装配,对于bean的id值是有要求的,id值需要与Java类上对应变量名称一致,否则也会出问题。

对于自动装配,总结如下:

  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作;
  • 使用按类型装配时,必须保障容器中相同类的bean唯一,推荐使用;
  • 使用按名称装配时,必须保障容器中具有指定名称的bean,因变量名与配置耦合,不推荐使用;
  • 自动装配优先级低于setter注入与构造器的注入,同时出现时自动装配失效。

2. 构造器注入

使用构造方法进行注入,原Book2ServiceImpl类修改为:
Book2ServiceImpl

package com.bh.service.Impl;

import com.bh.dao.Book2Dao;
import com.bh.service.Book2Service;

public class Book2ServiceImpl implements Book2Service {
    private Book2Dao book2Dao;
    public Book2ServiceImpl(Book2Dao book2Dao) {
        this.book2Dao = book2Dao;
    }

    public void save() {
        book2Dao.save();
    }
}

上述applicationContext.xml配置文件修改为如下:
在这里插入图片描述
运行结果同上述正常运行结果;
如果构造方法中有简单类型,constructor-arg标签如下:

<constructor-arg name="name" value="liuze"/>

但是这种方式一旦Java类变量名称修改了,配置文件也需要进行相应的名称修改,可以把name属性去掉,用index来代替,index值从0开始,表示Java类构造方法中形参的位置。
请添加图片描述

3. 集合注入

比如在一个Java类中有一些集合类型的变量,如数组、List、Set、Map、Properties,参考示例如下(使用setter注入):
RandomObject

package com.bh.other;

import java.util.*;

public class RandomObject {

    private int[] arrObj;
    private List<String> listObj;
    private Set<String> setObj;
    private Map<String,String > mapObj;
    private Properties propertiesObj;

    public void setArrObj(int[] arrObj) {
        this.arrObj = arrObj;
    }

    public void setListObj(List<String> listObj) {
        this.listObj = listObj;
    }

    public void setSetObj(Set<String> setObj) {
        this.setObj = setObj;
    }

    public void setMapObj(Map<String, String> mapObj) {
        this.mapObj = mapObj;
    }

    public void setPropertiesObj(Properties propertiesObj) {
        this.propertiesObj = propertiesObj;
    }

    public void save(){

        System.out.println("保存数据。。。");
        System.out.println(Arrays.toString(arrObj));
        System.out.println(listObj);
        System.out.println(setObj);
        System.out.println(mapObj);
        System.out.println(propertiesObj);
    }
}

applicationContext.xml配置文件为:

<bean id="randomObject" class="com.bh.other.RandomObject">
    <property name="arrObj">
         <array>
             <value>123</value>
             <value>456</value>
             <value>789</value>
         </array>
     </property>
     <property name="listObj">
         <list>
             <value>abc</value>
             <value>efg</value>
             <value>hij</value>
         </list>
     </property>
     <property name="setObj">
         <set>
             <value>abc</value>
             <value>efg</value>
             <value>hij</value>
             <value>abc</value>
         </set>
     </property>
     <property name="mapObj">
         <map>
             <entry key="name" value="liuze"/>
             <entry key="age" value="22"/>
             <entry key="address" value="hunan"/>
         </map>
     </property>
     <property name="propertiesObj">
         <props>
             <prop key="name">liuze</prop>
             <prop key="age">23</prop>
             <prop key="address">hunan</prop>
         </props>
     </property>
 </bean>

运行结果:
请添加图片描述

怎样利用上述知识对数据源对象进行注入呢?
applicationContext.xml

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl" value="jdbc::mysql://localhost:3306/d_test"/>
    <property name="user" value="root"/>
    <property name="password" value="sxx123"/>
</bean>

依旧使用setter注入方式即可,那么怎样加载自定义的properties文件呢?这就是说到开头讲的那个aplicationContext.xml文件了,是不是发现这个文件开头那个看不懂的链接比默认的多了几个,那是用于开启context命名空间的。
现在在resources文件夹有一个jdbc.properties文件如下:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc::mysql://localhost:3306/d_test
jdbc.username=root
jdbc.password=sxx123

aplicationContext.xml如何读取这些数据,如下:
请添加图片描述
运行结果:
请添加图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。