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

  • 相关阅读:
    TreeList 树形控件 实现带三种状态的CheckBox
    SQL 左外连接,右外连接,全连接,内连接(转)
    在DataTable中进行数据查询 (转)
    uva10594 Data Flow最小费用流,两个代码区别不大(我没看出区别),为什么一个对,另一个超时!!
    SGU142 Keyword好题
    uva 10881
    南京理工1747(数论)WA了好多遍!
    CF161D 树形dp
    uva 11646(大水题几何分类)
    求a加到b二进制加法有多少次进位。
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9249548.html
Copyright © 2011-2022 走看看