Spring——依赖注入的方式

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

依赖注入(DI)

依赖注入(DI)是一个过程,通过该过程,对象只能通过构造函数参数,工厂方法的参数或在构造或创建对象实例后在对象实例上设置的属性来定义其依赖关系(即,与它们一起工作的其他对象)。从工厂方法返回。然后,容器在创建 bean 时注入那些依赖项。从根本上讲,此过程是通过使用类的直接构造或服务定位器模式来自己控制其依赖关系的实例化或位置的 Bean 本身的逆过程(因此称为 Control Inversion)。

使用 DI 原理,代码更简洁,当为对象提供依赖项时,去耦会更有效。该对象不查找其依赖项,也不知道依赖项的位置或类。结果,您的类变得更易于测试,尤其是当依赖项依赖于接口或抽象 Base Class 时,它们允许在单元测试中使用存根或模拟实现。

DI 存在两个主要变体:基于构造函数的依赖注入和基于 Setter 的依赖注入。

1、构造器注入

1.使用无参构造创建对象(默认使用)

  public User() {
    }
复制代码

2.使用有参构造创建对象

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
复制代码
  • 1.构造函数参数下标索引(从0开始)

    您可以使用index属性来显式指定构造函数参数的索引

    <bean id="user" class="com.cheng.pojo.User">
        <constructor-arg index="0" value="spring"></constructor-arg>
        <constructor-arg index="1" value="3"></constructor-arg>
    </bean>
    复制代码
  • 2.构造函数参数类型匹配

    使用type属性显式指定了构造函数参数的类型,则容器可以使用简单类型的类型匹配。当有两个同类型参数时,不建议使用。

    <bean id="user" class="com.cheng.pojo.User">
        <constructor-arg type="java.lang.String" value="spring"></constructor-arg>
        <constructor-arg type="int" value="3"></constructor-arg>
    </bean>
    复制代码
  • 3.构造函数参数名称

    可以使用构造函数参数名称来消除歧义:

    <bean id="user" class="com.cheng.pojo.User">
        <constructor-arg name="name" value="spring"/>
        <constructor-arg name="age" value="3"/>
    </bean>
    复制代码

2、Set注入方式(常用)

  • 依赖注入:Set注入
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性,由容器来注入

环境搭建

  • 1.复杂类型

    package com.cheng.pojo;
    
    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
        @Override
        public String toString() {
            return "Address{" +
                    "address='" + address + '\'' +
                    '}';
        }
    }
    复制代码
    package com.cheng.pojo;
    
    import java.util.*;
    
    public class Student {
        private  String name;
        private Address address;
        private String[] books;
        private List<String> hobbys;
        private Map<String,String> card;
        private Set<String> games;
        private String wife;
        private Properties info;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        public String[] getBooks() {
            return books;
        }
    
        public void setBooks(String[] books) {
            this.books = books;
        }
    
        public List<String> getHobbys() {
            return hobbys;
        }
    
        public void setHobbys(List<String> hobbys) {
            this.hobbys = hobbys;
        }
    
        public Map<String, String> getCard() {
            return card;
        }
    
        public void setCard(Map<String, String> card) {
            this.card = card;
        }
    
        public Set<String> getGames() {
            return games;
        }
    
        public void setGames(Set<String> games) {
            this.games = games;
        }
    
        public String getWife() {
            return wife;
        }
    
        public void setWife(String wife) {
            this.wife = wife;
        }
    
        public Properties getInfo() {
            return info;
        }
    
        public void setInfo(Properties info) {
            this.info = info;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", address=" + address.toString() +
                    ", books=" + Arrays.toString(books) +
                    ", hobbys=" + hobbys +
                    ", card=" + card +
                    ", games=" + games +
                    ", wife='" + wife + '\'' +
                    ", info=" + info +
                    '}';
        }
    }
    复制代码
  • 2.真实测试对象

    //实现下面所有属性的注入
    private  String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
    复制代码
  • 3.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean id="address" class="com.cheng.pojo.Address"></bean>
    
        <bean id="student" class="com.cheng.pojo.Student">
            <!--第一种:普通值的注入,用value-->
            <property name="name" value="万里"/>
            <!--第二种:bean的注入,ref-->
            <property name="address" ref="address"/>
            <!--第三种:数组注入-->
            <property name="books" >
                <array>
                    <value>西游记</value>
                    <value>红楼梦</value>
                    <value>水浒传</value>
                    <value>三国演义</value>
                </array>
            </property>
            <!--第四种:List注入-->
            <property name="hobbys">
                <list>
                    <value>打游戏</value>
                    <value>看电影</value>
                    <value>敲代码</value>
                </list>
            </property>
            <!--第五种:Map注入-->
            <property name="card">
                <map>
                    <entry key="姓名" value="万里"/>
                    <entry key="系别" value="信息工程系"/>
                    <entry key="年级" value="18级"/>
                    <entry key="专业" value="计算机科学与技术"/>
                </map>
            </property>
            <!--第六种:Set注入-->
            <property name="games">
                <set>
                    <value>LOL</value>
                    <value>COC</value>
                    <value>BOB</value>
                </set>
            </property>
            <!--第七种:Null注入-->
            <property name="wife">
                <null/>  <!--等价于student.setWife(null);-->
            </property>
    <!--<property name="wife" value=""> 等价于student.setWife(""); 将wife属性设置为空的字符串值-->
    
            <!--第八种:properties注入-->
            <property name="info">
                <props>
                    <prop key="学号">08090335615</prop>
                    <prop key="姓名">万里</prop>
                </props>
            </property>
        </bean>
    </beans>
    复制代码
  • 4.测试类

    import com.cheng.pojo.Student;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            Student student = (Student) context.getBean("student");
            System.out.println(student.toString());
        }
    }
    
    复制代码

    测试结果:

    Student{name='万里', address=Address{address='null'}, 
    books=[西游记, 红楼梦, 水浒传, 三国演义], 
    hobbys=[打游戏, 看电影, 敲代码], 
    card={姓名=万里, 系别=信息工程系, 年级=18级, 专业=计算机科学与技术}, 
    games=[LOL, COC, BOB], 
    wife='null', 
    info={学号=08090335615, 姓名=万里}}
    复制代码

3、拓展方式注入

p命名空间注入和c命名空间注入,不能直接使用,需要导入约束

​ p命名空间注入 xmlns:p="www.springframework.org/schema/p"

​ c命名空间注入 xmlns:c="www.springframework.org/schema/c"

1.环境搭建

package com.cheng.pojo;

public class User {
    private String name;
    private int age;
    private Address address;

    public User() {
    }

    public String getName() {
        return name;
    }

    public User(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }
}
复制代码

2.userbeans.xml

  • p命名空间注入

    <?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:p="http://www.springframework.org/schema/p"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--p命名空间注入,可以直接注入属性的值,也可以注入引用-->
        <bean id="user" class="com.cheng.pojo.User"
              p:name="万里"
              p:age="3"
              p:address-ref="address"/>
    </beans>
    复制代码
  • c命名空间注入

    <?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:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--c命名空间注入,通过构造器注入,construct-org -->
        <bean id="user2" class="com.cheng.pojo.User" c:name="万里" c:age="3" c:address-ref="address"/>
    </beans>
    复制代码

测试类

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = context.getBean("user2", User.class);//用了反射后就不用类型强转了
        System.out.println(user);
}
复制代码

猜你喜欢

转载自juejin.im/post/7018722673345691655