• Spring5【四】依赖注入(DI)


    6、依赖注入(DI)

    依赖注入(Dependency Injection,DI)

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

    6.1 构造器注入

    之前的案例已经使用

    6.2 set 方式注入【重点】

    6.2.0 环境搭建

    1. 复杂类型

      public class Address {
          private String address;
      
          getXxx()/setXxx()/toString()
      }
      
    2. 真实测试对象

      public class Student {
      
          private String name;
          private Address address;
          private String[] books;
          private List<String> hobbies;
          private Map<String,String> card;
          private Set<String> games;
          private String wife;
          private Properties info;
          
          getXxx()/setXxx()/toString()
      }
      
    3. beans.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="student" class="com.song.pojo.Student">
              <!--第一种:普通值注入,value -->
              <property name="name" value="张三"/>
          </bean>
      
      </beans>
      
    4. 测试类

      public class MyTest {
      	public static void main(String[] args) {
          	ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
          	Student student = (Student)context.getBean("student");
          	System.out.println(student.getName());
      	}
      }
      

    6.2.1 普通值(常量)注入

    <bean id="student" class="com.song.pojo.Student">
        <!--普通值注入,value -->
        <property name="name" value="张三"/>
    </bean>
    

    6.2.2 Bean 注入,引用

    <bean id="address" class="com.song.pojo.Address">
        <property name="address" value="北京"/>
    </bean>
    
    <bean id="student" class="com.song.pojo.Student">
        <!--Bean 注入,ref-->
        <property name="address" ref="address"/>
    </bean>
    

    6.2.3 数组注入

    <!--数组注入-->
    <property name="books">
        <array>
            <value>红楼梦</value>
            <value>西游记</value>
            <value>水浒传</value>
            <value>三国演义</value>
        </array>
    </property>
    

    6.2.4 list 注入

    <!-- list 注入-->
    <property name="hobbies">
        <list>
            <value>打球</value>
            <value>唱歌</value>
            <value>跳舞</value>
        </list>
    </property>
    

    6.2.5 map 注入

    <!-- map 注入-->
    <property name="card">
        <map>
            <entry key="身份证" value="123456"/>
            <entry key="银行卡" value="456789"/>
        </map>
    </property>
    

    6.2.6 set 注入

    <!-- set 注入-->
    <property name="games">
        <set>
            <value>LOL</value>
            <value>COC</value>
            <value>BOB</value>
        </set>
    </property>
    

    6.2.7 null 注入

    <!-- null 注入-->
    <!--<property name="wife" value=""/>-->
    <property name="wife">
        <null/>
    </property>
    

    6.2.8 properties 注入

    <!-- properties 注入-->
    <property name="info">
        <props>
            <prop key="driver">2018020202</prop>
            <prop key="url">男</prop>
            <prop key="username">张三</prop>
            <prop key="password">123456</prop>
        </props>
    </property>
    

    测试:

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student)context.getBean("student");
        System.out.println(student.toString());
    }
    

    测试结果:

    Student{
         name='张三',
         address=Address{address='北京'},
         books=[红楼梦, 西游记, 水浒传, 三国演义],
         hobbies=[打球, 唱歌, 跳舞],
         card={身份证=123456,银行卡=456789},
         games=[LOL, COC, BOB],
         wife='null',
         info={password=123456,url=男,driver=2018020202,userme=张三}
    }
    

    6.3 拓展方式注入(p 命名空间和 c 命名空间)

    实体类:

    public class User {
    
        private String name;
        private int age;
    
        有参构造/无参构造/get/set/toString……
    }
    

    beans.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:p="http://www.springframework.org/schema/p"
           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">
    
        <!-- p 命名空间注入,可以直接注入属性的值:property -->
        <bean id="user" class="com.song.pojo.User" p:name="张三" p:age="18"/>
    
        <!-- c 命名空间注入,通过构造器注入:construct-arg -->
        <bean id="user2" class="com.song.pojo.User" c:age="18" c:name="李四"/>
    
    </beans>
    

    测试:

    @Test
        public void test2(){
            ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
    //        User user = (User) context.getBean("user");
    //        User user = context.getBean("user", User.class); // 第二个参数写上,就不用强转了
            User user = context.getBean("user2", User.class);
            System.out.println(user);
    
        }
    

    结果:

    //User{name='张三', age=18}
    User{name='李四', age=18}
    

    注意:不能直接使用,必须先在头文件中加入约束文件。

    • p 命名空间约束文件:xmlns:p="http://www.springframework.org/schema/p"

    • p 命名空间类似于 set 方法注入,bean 实体类中必须有无参构造

    • c 命名空间约束文件:xmlns:c="http://www.springframework.org/schema/c"

    • c 命名空间注入类似于构造器注入,bean 实体类中必须有有参构造

    6.4 bean 的作用域(Bean scopes)

    在 Spring 中,那些组成应用程序的主体及由 Spring IoC 容器所管理的对象,被称之为 bean。简单地讲,bean 就是由 IoC 容器初始化、装配及管理的对象。

    官方文档:

    Scope Description
    singleton (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
    prototype Scopes a single bean definition to any number of object instances.
    request Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
    session Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
    application Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
    websocket Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
    1. 单例模式(Spring 默认机制)

      当一个 bean 的作用域为 Singleton,那么 Spring IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。

      Singleton 是单例类型,就是在创建起容器时就同时自动创建了一个 bean 的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。

      注意:Singleton 作用域是 Spring 中的缺省作用域。显式表示为:

      <bean id="user" class="com.song.pojo.User" scope="singleton"/>
      
      @Test
      public void test2(){
          ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
      
          User user = context.getBean("user", User.class);
          User user2 = context.getBean("user", User.class);
          System.out.println(user == user2); // true
      }
      
    2. 原型模式

      每次从容器中 get 时,都会产生一个新对象。

      当一个 bean 的作用域为 Prototype,表示一个 bean 定义对应多个对象实例。Prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。

      Prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象

      根据经验,对有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。

      <bean id="user" class="com.song.pojo.User" scope="prototype"/>
      
      @Test
      public void test2(){
          ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
      
          User user = context.getBean("user", User.class);
          User user2 = context.getBean("user", User.class);
          System.out.println(user == user2); // false
      }
      
    3. 其余的 request、session、application 这些只能在 web 开发中使用,只能用在基于 web 的 Spring ApplicationContext 环境。

  • 相关阅读:
    进程和阻塞
    docker简介
    python===lambda匿名函数===day15
    python----生成器, 生成器函数, 推倒式---13
    python----函数参数---10天
    python---函数 第九天
    python===文件===第八天
    python===基本数据类型 基本增删改查 ===深浅拷贝==第七天
    20180802 (个别内置方法)
    20180730 (面向对象的反射,内置方法)
  • 原文地址:https://www.cnblogs.com/Songzw/p/13170105.html
Copyright © 2020-2023  润新知