zoukankan      html  css  js  c++  java
  • Spring学习(三)

    DI (Dependency Injection)

    1、依赖注入,组件之间的依赖关系由容器在运行期间决定。Ioc容器注入应用程序某个对象,它所需要的外部资源(包括对象,资源,常量数据)。

    birthdate需要用到date类型的一个对象,引用了d的对象就是一种DI(依赖注入),s.setBirthdate( d )依赖一个date类型的对象,注入就是将date类型的对象set进去。

    <bean id="d" class="java.util.Date" />
    <bean id="s" class="io.spring.ioc.base.Student" >
        <property name="id" value="1001" />
        <property name="name" value="张三丰" />
         <property name="gender" value="男" />
        <property name="birthdate" ref="d" />
    </bean>

    相当于s.setBirthdate( d ),也可以指定内部的bean

    <bean id="s" class="io.spring.ioc.base.Student">
        <property name="id" value="1001" />
        <property name="name" value="张三丰" />
        <property name="gender" value="男" />
        <property name="birthdate" > 
            <bean class="java.util.Date" />
        </property> 
    </bean>   

    相当于s.setBirthdate( new Date )。

    Spring Ioc容器

    1、具有依赖注入功能的容器。负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。在Spring中BeanFactory是Ioc容器的实际代表者。BeanFactory接口提供了IoC容器的基本功能。Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中各个对象进行实例化及装配。

    Spring IoC容器注入依赖资源的方式

    1、Spring IoC容器注入依赖资源的方式有两种setter注入和构造方法注入。

    2、setter注入, ( setter-base ),提供setter方法进行注入,依赖于无参构造和setter方法

    • Spring Framework 3.0 之前 ,使用property标记来来指定属性的注入值
      <bean id="customer" class="ecut.ioc.di.Customer" > c.setId(1002)
          <property name="id" value="1002" />
          <property name="name" value="张翠山" />
          <property name="gender" value="男" />
          <property name="birthdate" ref="date" />
      </bean>

      通过bean标记来声明这个bean,使用bean标记的id或name属性来指定bean的名称 , bean的class属相来指定bean的类型(具体的不是抽象的,不然需要修改abstract属性为true),name属性指定setter方法对应的名称,比如setBirthdate就写birthdate,ref属性用来指定需要引用的那个已经存在的bean的名称,普通类型用value,需要引用的类型使用ref。

    • Spring Framework 3.0 开始支持 p 命名空间为属性注入值 ,也依赖于无参构造和setter方法
      <!-- setter方法注入, 使用P命名空间(property namespace,需要提供p命名空间)-->
      <bean id="customer" 
                   class="ecut.ioc.di.Customer" 
                   p:id="1002" 
                   p:name="张翠山"
                   p:gender="男" 
                   p:birthdate-ref="date" />

      普通类型p:name="value",需要引用的类型使用p:name-ref="引用bean的id"

    • 测试案例

      Customer类

      package ecut.ioc.di;
      
      import java.util.Date;
      
      public class Customer {
      
          private Integer id;
          private String name;
          private char gender;
          private Date birthdate;
          
          public Customer() {
              super();
              System.out.println( "调用 Customer 无参构造创建对象" );
          }
          
          public Customer(Integer id, String name, char gender) {
              super();
              this.id = id;
              this.name = name;
              this.gender = gender;
              System.out.println( "调用 Customer( Integer , String , char ) 创建对象" );
          }
      
          public Customer(Integer id, String name, char gender, Date birthdate) {
              super();
              this.id = id;
              this.name = name;
              this.gender = gender;
              this.birthdate = birthdate;
              System.out.println( "调用 Customer( Integer , String , char , Date ) 创建对象" );
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
              System.out.println( "为id属性赋值: " + id );
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
              System.out.println( "为name属性赋值: " + name );
          }
      
          public char getGender() {
              return gender;
          }
      
          public void setGender(char gender) {
              this.gender = gender;
              System.out.println( "为gender属性赋值: " + gender );
          }
      
          public Date getBirthdate() {
              return birthdate;
          }
      
          public void setBirthdate(Date birthdate) {
              this.birthdate = birthdate;
              System.out.println( "为birthdate属性赋值: " + birthdate );
          }
      
      }

      setter-injection.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"
          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
      
          <bean id="date" class="java.util.Date" />
      
          <!-- setter方法注入, 使用P命名空间(property namespace,需要提供p命名空间)-->
          <bean id="customer" 
                   class="ecut.ioc.di.Customer" 
                   p:id="1002" 
                   p:name="张翠山"
                   p:gender="男" 
                   p:birthdate-ref="date" />
                   
          <!-- 通过bean标记来声明这个bean
                使用bean标记的id或name属性来指定bean的名称 ,
               bean的class属相来指定bean的类型(具体的不是抽象的,不然需要修改abstract属性为true),
               name属性指定setter方法对应的名称,比如setBirthdate就写birthdate,
               ref属性用来指定需要引用的那个已经存在的bean的名称-->
          <!--Customer c = new Customer(); -->
          <!--<bean id="customer" class="ecut.ioc.di.Customer" > c.setId(1002)
              <property name="id" value="1002" />
              <property name="name" value="张翠山" />
              <property name="gender" value="男" />
              <property name="birthdate" ref="date" />
          </bean>
          -->
          
      
      
      </beans>

      测试类

      package ecut.ioc.di;
      
      import org.springframework.context.support.AbstractApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class TestSetterInjection {
      
          public static void main(String[] args) {
              //指定configuration metadata配置元数据
              String configLocations = "classpath:ecut/**/di/setter-injection.xml" ;
              //创建spring IOC容器
              AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
              //ready for use (此时可以从指定的IOC容器中获取指定名称的bean实例了)
              Customer c = container.getBean( "customer" , Customer.class );
              //从容器中获取的bean实例中获取属性值
              System.out.println( c.getId() );
              
              System.out.println( c.getName() );
              
              System.out.println( c.getGender() );
              
              System.out.println( c.getBirthdate() );
              //关闭spring的IOC容器
              container.close();
              
          }
      
      }

     3、构造方法注入 : ( constructor-base )通过构造方法往里面传入值

    • 测试案例

      constructor-injection.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"
          xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
      
          <bean id="date" class="java.util.Date" />
          
          <!-- constructor 调用有参数的构造 -->
          <bean id="customer"  class="ecut.ioc.di.Customer" >
              <!-- 在bean标记内部使用constructor-arg标记来指定构造方法的参数为 ,
              也可以根据type匹配相应的参数如果这个类型参数唯一,
              也可以指定index来指定参数,若和参数顺序一致index可以省略,
               name是指参数名称,value是指定的参数值 -->
              <constructor-arg name="id"  type="java.lang.Integer" value="1003" />
              <constructor-arg name="name" type ="java.lang.String"  value="殷素素" />
              <constructor-arg name="gender" value="女" />
              <!-- 如果参数类型不是简单类型就需要使用ref去引用其他的bean -->
              <constructor-arg name="birthdate" ref="date" />
          </bean>
          
          <!-- <bean id="customer"  class="ecut.ioc.di.Customer" >
              在bean标记内部使用constructor-arg标记来指定构造方法的参数为 ,
              也可以根据type匹配相应的参数如果这个类型参数唯一,
              也可以指定index来指定参数,若和参数顺序一致index可以省略,
               name是指参数名称,value是指定的参数值 
              <constructor-arg type="java.lang.Integer" value="1003" />
              <constructor-arg type ="java.lang.String"  value="殷素素" />
              <constructor-arg value="女" />
              <constructor-arg  ref="date" />
          </bean> -->
          
          <!-- constructor 调用有参数的构造 -->
          <!-- <bean id="customer"  class="ecut.ioc.di.Customer" >
              在bean标记内部使用constructor-arg标记来指定构造方法的参数为 ,
              也可以根据type匹配相应的参数如果这个类型参数唯一,
              也可以指定index来指定参数,若和参数顺序一致index可以省略,
               name是指参数名称,value是指定的参数值 
              <constructor-arg name="id" value="1003" />
              <constructor-arg name="name" value="殷素素" />
              <constructor-arg name="gender" value="女" />
              <constructor-arg name="birthdate" ref="date" />
          </bean> -->
          
          
          <!-- <bean id="customer"  class="ecut.ioc.di.Customer" >
              在bean标记内部使用constructor-arg标记来指定构造方法的参数为 ,
              也可以根据type匹配相应的参数如果这个类型参数唯一,
              也可以指定index来指定参数,若和参数顺序一致index可以省略,
               name是指参数名称,value是指定的参数值 
              <constructor-arg value="1003" />
              <constructor-arg value="殷素素" />
              <constructor-arg value="女" />
              <constructor-arg ref="date" />
          </bean> -->
          
          <!-- <bean id="customer"  class="ecut.ioc.di.Customer" >
              在bean标记内部使用constructor-arg标记来指定构造方法的参数为 ,
              也可以根据type匹配相应的参数如果这个类型参数唯一,
              也可以指定index来指定参数,若和参数顺序一致index可以省略,
               name是指参数名称,value是指定的参数值 
              <constructor-arg index="0" value="1003" />
              <constructor-arg index="2" value="女" />
              <constructor-arg index="1" value="殷素素" />
              <constructor-arg index="3" ref="date" />
          </bean> -->
          
      </beans>

      在bean标记内部使用constructor-arg标记来指定构造方法的参数为 ,也可以根据type匹配相应的参数如果这个类型参数唯一,也可以指定index来指定参数,若和参数顺序一致index可以省略,name是指参数名称,value是指定的参数值。

      测试类

      package ecut.ioc.di;
      
      import org.springframework.context.support.AbstractApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class TestConstructorInjection {
      
          public static void main(String[] args) {
              //指定configuration metadata配置元数据
              String configLocations = "classpath:ecut/**/di/constructor-injection.xml" ;
              //创建spring IOC容器
              AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
              //ready for use (此时可以从指定的IOC容器中获取指定名称的bean实例了)
              Customer c = container.getBean( "customer" , Customer.class );
              //从容器中获取的bean实例中获取属性值
              System.out.println( c.getId() );
              
              System.out.println( c.getName() );
              
              System.out.println( c.getGender() );
              
              System.out.println( c.getBirthdate() );
              //关闭spring的IOC容器
              container.close();
              
          }
      
      }

      如果在Customer类中写了带参数的构造最好写 无参构造,只写有参构造,虚拟机不会再分配无参构造, 因为没有提供无参构造会抛出异常BeanCreationException,没有找到默认构造方法 No default constructor found;

    Spring IoC容器注入集合

    1、Spring不仅能注入简单类型数据,还能注入集合(Collection、Set、List)类型、数组(Array)类型、字典(Map)类型数据、Properties类型数据。

    2、3.0之前的注入方式:在 <property> 标签 内部 使用 set 、list 、map 、props 标签实现注入: normal-injection.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:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
        
        <bean id="birthdate" class="java.util.Date" />
        
        <bean id="findFriend" class="java.util.Date" />
    
        <bean id="user" class="ecut.ioc.collection.User">
            <property name="id" value="1001" />
            <property name="name" value="张三丰" />
            
            <!-- 注入 Set 集合 -->
            <property name="hobby">
                <set>
                    <value>吃饭</value>
                    <value>睡觉</value>
                    <value>泡妞/被泡</value>
                </set>
            </property>
            
            <!-- 注入 List 集合 -->
            <property name="luckDay">
                <list>
                    <!-- 如果不是基本数据类型及其包装类型,通过ref 来引用-->
                    <ref bean="birthdate"/>
                    <ref bean="findFriend"/>
                </list>
            </property>
            
            <!-- 注入 Map 集合 -->
            <property name="score">
                <map>
                    <entry key="前端" value="45" />
                    <entry key="后端" value="54" />
                </map>
            </property>
            
            <!-- 注入 Properties 集合 -->
            <property name="address">
                <props>
                    <prop key="软件楼">东理北门内,太谷路旁,软件楼一楼厕所边的那个门</prop>
                    <prop key="宿舍">东理南区研一好望角</prop>
                </props>
            </property>
            
        </bean>
    
    
    </beans>

    3、3.0全新的注入方式:使用 Spring 3.0 开始提供的 util 命名空间,结合 <property> 或 p 命名空间实现注入: util-injection.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:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd">
        
        <bean id="birthdate" class="java.util.Date" />
        
        <bean id="findFriend" class="java.util.Date" />
    
        <util:set id="hobby" set-class="java.util.HashSet">
            <value>吃饭</value>
            <value>睡觉</value>
            <value>泡妞/被泡</value>
        </util:set>
    
        <util:list id="luckDay" list-class="java.util.ArrayList">
            <ref bean="birthdate" />
            <ref bean="findFriend" />
        </util:list>
    
        <util:map id="score" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.Integer">
            <entry key="前端" value="45" />
            <entry key="后端" value="54" />
        </util:map>
    
        <util:properties id="address">
            <prop key="软件楼">东理北门内,太谷路旁,软件楼一楼厕所边的那个门</prop>
            <prop key="宿舍">东理南区研一好望角</prop>
        </util:properties>
        
        <!-- <bean id="user" class="io.spring.ioc.collection.User" p:address-ref="address"> -->
        <bean id="user" class="ecut.ioc.collection.User" >
            <property name="id" value="1001" />
            <property name="name" value="张三丰" />
            
            <!-- 注入 Set 集合 -->
            <property name="hobby" ref="hobby"/>
            
            <!-- 注入 List 集合 -->
            <property name="luckDay" ref="luckDay" />
            
            <!-- 注入 Map 集合 -->
            <property name="score" ref="score"/>
            
            <!-- 注入 Properties 集合 -->
            <property name="address" ref="address"/>
            
        </bean>
    
    
    </beans>

    转载请于明显处标明出处

    https://www.cnblogs.com/AmyZheng/p/9249548.html

  • 相关阅读:
    streamsets 集成 cratedb 测试
    streamsets k8s 部署试用
    streamsets rest api 转换 graphql
    StreamSets sdc rpc 测试
    StreamSets 相关文章
    StreamSets 多线程 Pipelines
    StreamSets SDC RPC Pipelines说明
    StreamSets 管理 SDC Edge上的pipeline
    StreamSets 部署 Pipelines 到 SDC Edge
    StreamSets 设计Edge pipeline
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9249548.html
Copyright © 2011-2022 走看看