• [Spring Framework]DI依赖注入②(自动装配、集合注入)


    依赖自动装配

    在前文我们所提到的setter注入、构造器注入都需要配置,在我看来是有点麻烦的,为了简化我们的代码、提高我们的效率,我们可以使用依赖自动装配,那么什么是依赖自动装配呢?

    IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配

    自动装配存在以下几种方式:

    • 按类型(常用)
    • 按名称
    • 按构造方法(很少用我们不去了解)
    • 不启用自动装配

    接下来我们还是借用前文的工程结构来做两个实验:

    在前文中:

    我们的Spring配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="bookDao" class="impl.BookDaoImpl"/>
        <bean id="bookService" class="impl.BookServiceImpl">
            <property name="bookDao" ref="bookDao"/>
        </bean>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    BookServiceImpl类:

    public class BookServiceImpl implements BookService {
        private BookDao bookDao;
    
        public void setBookDao(BookDao bookDao) {
            this.bookDao = bookDao;
        }
    
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    App:

    public class App2 {
        public static void main(String[] args) {
            //获取容器
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookService bookService = (BookService) ctx.getBean("bookService");
    
            bookService.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接下来我们使用自动装配:

    首先我们将标签删除,然后在标签中添加autowire属性:

    <bean id="bookDao" name="bookBookDao" class="impl.BookDaoImpl"/>
    <!--autowire属性:开启自动装配,通常使用按类型装配-->
    <bean id="bookService" class="impl.BookServiceImpl" scope="prototype" autowire="byType"/>
    
    • 1
    • 2
    • 3

    接下来我们在运行App2,结果正常:
    在这里插入图片描述

    注意:
    ①需要注入属性的类中对应属性的setter方法不能省略
    ②被注入的对象必须要被Spring的IOC容器管理
    ③按照类型在Spring的IOC容器中如果找到多个对象,会报NoUniqueBeanDefinitionException

    也就是说如果使用byType,那么容器中有且仅有一个bean的类型与之对应,否则就会报错!

    那么假如真有两个bean的类型都满足怎么办呢?(当然这种情况很少发生,byType可以放心使用)

    我们可以使用:byName

    <bean id="bookDao" name="bookBookDao" class="impl.BookDaoImpl"/>
    <bean id="bookService" class="impl.BookServiceImpl" scope="prototype" autowire="byName"/>
    
    • 1
    • 2

    注意事项:

    • 按照名称注入中的名称指的是什么?

      在这里插入图片描述

      • bookDao是private修饰的,外部类无法直接方法
      • 外部类只能通过属性的set方法进行访问
      • 对外部类来说,setBookDao方法名,去掉set后首字母小写是其属性名
        • 为什么是去掉set首字母小写?
        • 这个规则是set方法生成的默认规则,set方法的生成是把属性名首字母大写前面加set形成的方法名
      • 所以按照名称注入,其实是和对应的set方法有关,但是如果按照标准起名称,属性名和set对应的名是一致的
    • 如果按照名称去找对应的bean对象,找不到则注入Null

    • 当某一个类型在IOC容器中有多个对象,按照名称注入只找其指定名称对应的bean对象,不会报错

    最后对于依赖注入,需要注意一些其他的配置特征:

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

    集合注入

    前面我们已经能完成引入数据类型和简单数据类型的注入,但是还有一种数据类型集合,集合中既可以装简单数据类型也可以装引用数据类型,对于集合,在Spring中该如何注入呢?

    我们从以下几个方面入手:

    • 数组
    • List
    • Set
    • Map
    • Properties

    项目准备:

    实现了BookDao接口的BookDaoImpl:

    public class BookDaoImpl implements BookDao {
        private int[] array;
    
        private List<String> list;
    
        private Set<String> set;
    
        private Map<String,String> map;
    
        private Properties properties;
    
        public void save() {
            System.out.println("book dao save ...");
    
            System.out.println("遍历数组:" + Arrays.toString(array));
    
            System.out.println("遍历List" + list);
    
            System.out.println("遍历Set" + set);
    
            System.out.println("遍历Map" + map);
    
            System.out.println("遍历Properties" + properties);
        }
    
        public void setArray(int[] array) {
            this.array = array;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        public void setSet(Set<String> set) {
            this.set = set;
        }
    
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
    
        public void setProperties(Properties properties) {
            this.properties = properties;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    App3:

    public class AppForDICollection {
        public static void main( String[] args ) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            BookDao bookDao = (BookDao) ctx.getBean("bookDao");
            bookDao.save();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注入数组类型数据

    <property name="array">
        <array>
            <value>100</value>
            <value>200</value>
            <value>300</value>
        </array>
    </property>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注入List类型数据

    <property name="list">
        <list>
            <value>book</value>
            <value>apple</value>
            <value>fenda</value>
            <value>banana</value>
        </list>
    </property>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注入Set类型数据

    <property name="set">
        <set>
            <value>cat</value>
            <value>car</value>
            <value>cupple</value>
            <value>cola</value>
        </set>
    </property>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注入Map类型数据

    <property name="map">
        <map>
            <entry key="country" value="china"/>
            <entry key="province" value="henan"/>
            <entry key="city" value="kaifeng"/>
        </map>
    </property>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注入Properties类型数据

    <property name="properties">
        <props>
            <prop key="country">china</prop>
            <prop key="province">henan</prop>
            <prop key="city">kaifeng</prop>
        </props>
    </property>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    然后我们运行App3:
    在这里插入图片描述

    注意:
    ①property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写标签
    List的底层也是通过数组实现的,所以标签是可以混用
    集合中要添加引用类型,只需要把标签改成标签,这种方式用的比较少

  • 相关阅读:
    git切换分支
    【推送服务】【FAQ】Push Ki常见咨询合集5--消息回执类问题
    基于springboot小型车队管理系统毕业设计源码
    数据通讯基础
    uniapp截图功能的实现,需要用到HTML2canvas库
    初级算法之数组
    【Java SE】重写和重载的区别
    【软考】关键路径和松弛时间的定义和计算方式
    docker<应用分享>--本地镜像上传dockerhub、从dockerhub拉取镜像
    Unity技术手册-UGUI零基础详细教程-Toggle切换
  • 原文地址:https://blog.csdn.net/zyb18507175502/article/details/125738199