• Spring 03: xml的构造方法注入


    注入方式

    • 具体有3种注入方式:通过构造方法的 a.参数名称注入 b.参数下标注入 c.默认参数顺序注入

    参数名称注入

    • School实体类
    package com.example.pojo03;
    
    public class School {
        private String name;
        private String address;
    
        @Override
        public String toString() {
            return "School{" +
                    "name='" + name + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    
        public School(String name, String address) {
            this.name = name;
            this.address = address;
            System.out.println("School有参构造方法执行,实例对象被创建....");
        }
    }
    
    • applicationContext.xml
    
    
    
    <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="school" class="com.example.pojo03.School">
            <constructor-arg name="name" value="nefu"/>
            <constructor-arg name="address" value="哈尔滨"/>
        bean>
        
    beans>
    
    • 测试
    package com.example.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TestConstructor {
    
        //测试:通过构造方法的参数名称注入
        @Test
        public void testConstructorArgs(){
            //创建Spring容器
            ApplicationContext ac = new ClassPathXmlApplicationContext("source03/applicationContext.xml");
            //取出School对象并打印输出
            System.out.printf("School实例对象: " + ac.getBean("school"));
        }
    }
    
    • 测试结果
    School有参构造方法执行,实例对象被创建....
    School实例对象: School{name='nefu', address='哈尔滨'}
    
    Process finished with exit code 0
    

    参数下标注入

    • 实体类:新增Student实体类,持有School实例对象的引用
    package com.example.pojo03;
    
    public class Student {
        private String name;
        private int age;
        private School school;
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", school=" + school +
                    '}';
        }
    
        public Student(String name, int age, School school) {
            this.name = name;
            this.age = age;
            this.school = school;
            System.out.println("Student有参构造方法执行,实例对象被创建....");
        }
    }
    
    • applicationContext.xml:新增bean标签,注册Student实例对象
        
        <bean id="student" class="com.example.pojo03.Student">
            <constructor-arg index="0" value="荷包蛋"/>
            <constructor-arg index="1" value="20"/>
            <constructor-arg index="2" ref="school"/>
        bean>
    
    • 测试:新增测试方法
        //测试:通过构造方法的参数下标注入
        @Test
        public void testConstructorIndex(){
            //创建Spring容器
            ApplicationContext ac = new ClassPathXmlApplicationContext("source03/applicationContext.xml");
            //取出Student对象并打印输出
            System.out.printf("Student实例对象: " + ac.getBean("student"));
        }
    
    • 测试结果
    School有参构造方法执行,实例对象被创建....
    Student有参构造方法执行,实例对象被创建....
    Student实例对象: Student{name='荷包蛋', age=20, school=School{name='nefu', address='哈尔滨'}}
    
    Process finished with exit code 0
    

    默认参数顺序注入

    • applicationContext.xml:新增bean标签,通过构造方法默认参数顺序注册Student实例对象,注意将之前对Student实例对象的注册先注释掉
        
        <bean id="student02" class="com.example.pojo03.Student">
            <constructor-arg value="荷包蛋"/>
            <constructor-arg value="20"/>
            <constructor-arg ref="school"/>
        bean>
    
    • 测试:新增测试方法
        //测试:通过构造方法默认参数顺序注入
        @Test
        public void testConstructorDefaultOrder(){
            //创建Spring容器
            ApplicationContext ac = new ClassPathXmlApplicationContext("source03/applicationContext.xml");
            //取出Student对象并打印输出
            System.out.printf("Student实例对象: " + ac.getBean("student02"));
        }
    
    • 测试结果
    School有参构造方法执行,实例对象被创建....
    Student有参构造方法执行,实例对象被创建....
    Student实例对象: Student{name='荷包蛋', age=20, school=School{name='nefu', address='哈尔滨'}}
    
    Process finished with exit code 0
    

    注意

    前两种注入方式,由于一种依靠参数名和待注入值绑定,一种依靠参数下标和待注入值绑定,做到了注入值与待注入目标一一对应
    所以注入标签顺序随意,调换 < constructor-arg />标签的前后顺序,仍可正确注入数据

        
        <bean id="student" class="com.example.pojo03.Student">
            <constructor-arg index="0" value="荷包蛋"/>
            <constructor-arg index="2" ref="school"/>
            <constructor-arg index="1" value="20"/>
        bean>
    
    • 但是依靠参数默认顺序注入时,要严格参考实体类中待注入属性的顺序和类型,保证与标签中的待注入值的类型相同,不然会类型解析错误,数据注入失败
        
        <bean id="student02" class="com.example.pojo03.Student">
            <constructor-arg value="荷包蛋"/>
            <constructor-arg ref="school"/>
            <constructor-arg value="20"/>
        bean>
    
    • 容器启动时,School实例对象成功创建并注入数据,但创建Student对象时,待注入数据类型和目标属性类型不对应,类型解析错误,创建失败

    image

  • 相关阅读:
    bclinux aarch64 ceph 14.2.10 云主机 4节点 fio
    Cocoa-电子书目录
    计算机网络,网络(OSI)七层模型,三次握手四次挥手,get与post请求区别,网络IO(BIO\NIO\AIO),TCP与UDP区别
    k8s学习笔记-完整版
    流式编程 stream
    Apache Tomcat 云服务器的安装及环境的配置
    如何成功地将 OKR 推广到您的组织
    【记录】celery + mongodb 动态添加、更新定时任务时间
    GMAN: A Graph Multi-Attention Network for Traffic Prediction(2020AAAI)
    Lua篇笔记
  • 原文地址:https://www.cnblogs.com/nefu-wangxun/p/16607580.html