• Spring 学习笔记 ----依赖注入


    依赖注入 有三种方式,本文只学习下属性注入.

    属性注入

          属性注入即通过 setXxx方法()注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入方式是实际应用中最常用的注入方式。

    属性注入的实例

    属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。先看一个简单的例子
    package com.spring.model;
    
    
    public class Car {
    	/**
    	 *  系统为自动我们提供一个无参的构造方法
    	 */
    	private String brand;
    	private String color;
    	private int maxSpeed;
    	public void setBrand(String brand) {
    		this.brand = brand;
    	}
    	public void setColor(String color) {
    		this.color = color;
    	}
    	public void setMaxSpeed(int maxSpeed) {
    		this.maxSpeed = maxSpeed;
    	}
    }


    Car 类中定义了3个属性,并提供了对应的Setter方法.
    小提示:默认构造函数是不带参数的构造函数。Java语言规定,如果类中没有定义任何构造函数,则JVM自动为其生成一个默认的构造函数。反之,如果类中显示定义了构造函数,则JVM不会为其生成默认的构造函数。所以假设Car类中定义了一个带参的构造函数,如public Car(String brand),则需要同时提供一个默认构造函数public Car(),否则使用属性注入时将抛出异常。
    下面是在Spring配置文件中,对Car进行属性注入时的配置片段.
      <bean  id="car" class="com.spring.model.Car" >
            <property name="maxSpeed"><value>200</value></property>
            <property name="brand"><value>红旗CAT2</value> </property>
            <property name="color"><value>红色</value></property>
       </bean>
    我们配置了一个Car Bean,并为该Bean的三个属性提供了属性值。具体来说,Bean的每一个属性对应一个<property>标签,name为属性的名称,在Bean实现类中拥有与其对应的Setter方法:maxSpeed对应setMaxSpeed。

    注入参数详解

    字面值

    上面使用的方式就是字面值。

    引用其它Bean

    Spring IOC容器中定义的bean可以相互引用,IOC容器则充当红娘的角色。下面我们创建一个新的Boss类,Boss类中拥有一个Car类型的属性:
    package com.spring.model;
    
    public class Boss {
       private Car car=new Car();
    
    public Car getCar() {
    	return car;
    }
    //设置Car属性
    public void setCar(Car car) {
    	this.car = car;
    }
    ..........
    }
    boss 的Bean通过<ref>元素引用car Bean,建立起Boss对car的依赖。
       <!-- 1 car bean -->      
       <bean  id="car" class="com.spring.model.Car" />
       <bean id="boss" class="com.spring.model.Boss">
            <property name="car">
               <!--2 引用1处定义的car bean -->
               <ref bean="car"/>
            </property>
       </bean>
       
    <ref>元素可以通过以下三个属性引用容器中的其它Bean。
    (1)bean:通过该属性可以引用同一容器或父容器的Bean,这是最常见的形式。
    (2)local:通过该属性只能引用同一配置文件中定义的Bean,它可以利用XML解析器自动校验引用的合法性,以便在开发编写配置时能够及时发现并纠正错误;
    (3)parent:引用父容器中的Bean,如<ref parent="car">的配置说明car的Bean是父容器的Bean。

    为了说明子容器对父容器Bean的引用,来看一个具体的例子。假设有两个配置文件:beans1.xml 和beans2.xml,其中beans.xml被父容器加载,其配置内容如下:
    beans1.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-3.0.xsd">
               
               <!--1 在父容器定义的bean -->
               <bean id="car" class="com.spring.model.Car">
                  <property name="brand">
                     <value>红旗</value>
                  </property>
                  <property name="color" value="红色"/>
                  <property name="maxSpeed" value="200"/>
               </bean>
    </beans>
    beans2.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-3.0.xsd">
               
        <!--该bean和父容器的car bean具有相同的id-->
               <bean id="car" class="com.spring.model.Car">
                  <property name="brand">
                     <value>白旗CAR</value>
                  </property>
                  <property name="color" value="红色"/>
                  <property name="maxSpeed" value="200"/>
               </bean>        
               
          <bean id="boss" class="com.spring.model.Boss">
            <property name="car">
               <!-- 引用父容器的car,而非beans2.xml定义的car ,如果采用<ref bean="car" 则会引用本容器的car/>  -->
               <ref parent="car"/>
            </property>
          </bean>
    </beans>
    在beans1.xml中定义了一个car bean,在beans2.xml也定义了一个car Bean。分别通过父子容器加载beans1.xml和beans2.xml,beans2.xml中的boss通过<ref parent="car">将引用到父容器中的car.
    下面是分别和父子容器加载beans1.xml和beans2.xml配置文件的代码:
    	@Test  
    	public void test1(){
    	 //父容器
          ApplicationContext pFactory=new ClassPathXmlApplicationContext("beans1.xml");	 
         //指定pFactory为该容器的父容器
          ApplicationContext factory=new ClassPathXmlApplicationContext(new String[]{"beans2.xml"},pFactory);
           
          Boss boss=(Boss) factory.getBean("boss");
          System.out.println(boss.getCar().getBrand());
    
    	}
    运行后结果如下:
    红旗

    内部Bean

       如果car bean只被Boss bean引用,而不会被容器中任何其它的bean引用,则可以将car以内部bean的方式注入到Boss中。
          <bean id="boss" class="com.spring.model.Boss">
            <property name="car">
               <bean  class="com.spring.model.Car">
                    <property name="maxSpeed" value="200"/>
                    <property name="color" value="白色"/>
               </bean>
            </property>
          </bean>
    内部bean和JAVA代码中匿名内部类很相似,即没有名字,也不能被其它bean引用,只能在声明处为外部bean提供实例注入。 内部bean即使提供了id、name、scope属性,也会被忽略,scope默认为prototype类型.

    null值

         <property name="barnd">
               <value><null/> </value>
            </property>

    级联属性

    和Struts、Hibernate等框架一样,Spring支持级联属性的配置。假设我们在定义Boss时直接为Car的属性提供注入值,则可以采取以下的配置方式:
       <bean id="boss2" class="com.spring.model.Boss">
            <!-- 以原点的方式定义级别属性 -->
             <property name="car.brand" value="吉利Ct50"/>
          </bean>
    按照上面的配置,Spring将调用Boss.getCar.setBaran("吉利Ct50"),方法进行属性的注入操作。
    Spring 没有对级联属性的层级数进行限制,只要配置的Bean拥有对应于级联属性的类结构,就可以配置任意层级的级联属性,如<property name="car.wheel.brand" value="双星" />定义了具有三级结构的级联属性。

    集合类型属性

    java.util包中的集合类是最常用的数据结构类型,主要包括List、Set、Map、Properties,Spring为这些集合类型属性配置了专门的配置元素标签。
       List
    我们为Boss类添加一个List类型的favourites属性:
    package com.spring.model;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Boss {
     
    private List favourites=new ArrayList();
       
    public List getFavourites() {
    	return favourites;
    }
    public void setFavourites(List favourites) {
    	this.favourites = favourites;
    }}
    对应Spring 中的配置片段如下所示:
          <bean id="boss" class="com.spring.model.Boss">
               <property name="favourites">
                    <list>
                        <value>看报</value>
                        <value>赛车</value>
                        <value>高尔夫</value>
                    </list>
                </property>
          </bean>
    List属性既可以通过<value>注入字符串,也可以通过<ref>注入容器中其它的Bean.
    Set
    如果Boss的favourites属性时java.util.set.,则采用如下的配置方式:
          <bean id="boss" class="com.spring.model.Boss">
               <property name="favourites">
                    <set>
                        <value>看报</value>
                        <value>赛车</value>
                        <value>高尔夫</value>
                    </set>
                </property>
          </bean>
    Map
    下面我们为Boss添加一个Map类型的jobs属性:
    package com.spring.model;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Boss {
    	private Map jobs=new HashMap();
    
    	public Map getJobs() {
    		return jobs;
    	}
    
    	public void setJobs(Map jobs) {
    		this.jobs = jobs;
    	}
    	
    }
    在配置文件中,可以通过如下方式为jobs属性提供配置值:
          <bean id="boss" class="com.spring.model.Boss">
               <property name="jobs">
                   <map>
                      <!-- Map 第一个元素 -->
                       <entry>
                           <key><value>AM</value></key>
                           <value>会见客户</value>
                       </entry>
                       <!-- Map第二个元素 -->
                       <entry>
                           <key><value>PM</value></key>
                           <value>公司内部会议</value>
                       </entry>
                   </map>
               </property>
          </bean>
    假设某一Map元素的键和值都是对象,则可以采取以下的配置方式:
                      <entry>
                           <key><ref bean="keyBean"/> </key>
                           <ref bean="valueBean"/>
                       </entry>
    Properties
    Properties类型其实可以看成是Map类型的特例。Map元素的键和值可以为任何类型的对象,而Properties属性的键和值都只能是字符串,我们为Boss添加一个Properties类型的mail属性:
    package com.spring.model;
    
    import java.util.Properties;
    
    public class Boss {
      private Properties mails=new Properties();
    
    public Properties getMails() {
    	return mails;
    }
    
    public void setMails(Properties mails) {
    	this.mails = mails;
    }
    	
    }
    
    下面的配置片段为mails提供了配置:
       
          <bean id="boss" class="com.spring.model.Boss">
               <property name="mails">
                   <props>
                      <prop key="jobMail">john-office@taobao.com</prop>
                      <prop key="lifeMail">john-life@taobao.com</prop>
                   </props>
               </property>
          </bean>
    因为Properties键值对只能是字符串,因此其配置比Map的配置要简单一些,注意值的配置没有<value>子元素标签.

    强类型集合

    下面Boss类的jobTime属性采用强类型的Map类型:元素的键为String类型;而值为Integer类型。
    package com.spring.model;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class Boss {  
    	private Map<String,Integer> jobTime =new HashMap<String, Integer>();
    
    	public Map<String, Integer> getJobTime() {
    		return jobTime;
    	}
    
    	public void setJobTime(Map<String, Integer> jobTime) {
    		this.jobTime = jobTime;
    	}
    }
    
    在Spring中的配置和非强类型集合相同:
        <bean id="boss" class="com.spring.model.Boss">
               <property name="jobTime">
                    <map>
                       <entry>
                           <key> <value>会见客户</value></key>
                           <value>124</value>
                       </entry>  
                    </map>
               </property>
          </bean>
    但Spring 容器在注入强类型集合时,会判断元素的类型,将设置值转换为对应的数据类型。如上面代码中的设置项124将被转换为Integer类型.

    集合合并

    Spring2.0新增了集合合并的功能,允许子<bean>继承父<bean>中配置的同名属性值合并起来作为最终bean的属性值。
    <?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-3.0.xsd">
            
          <!-- 父bean -->   
          <bean id="parentBoss" abstract="true" class="com.spring.model.Boss">
                  <property name="favorites">
                      <set>
                          <value>看报</value>
                          <value>赛车</value>
                          <value>高尔夫</value>
                      </set>
                  </property>        
          </bean>
          
          <!-- 子bean -->
           <bean id="childBoss" class="com.spring.model.Boss" parent="parentBoss">
                  <property name="favorites">
                      <set merge="true">
                          <value>爬山</value>
                          <value>游泳</value>
                      </set>
                  </property>        
          </bean>
    </beans>
    在代码清单中,通过merge="true"属性指定子<bean>和父<bean>中的同名属性值进行合并,即子<bean>的favourites元素将最终拥有5个元素。如果设置merge="false",则不会和父<bean>同名集合属性进行合并,即子Bean的favourites属性集合只有两个元素.
    	@Test 
    	public void test2(){
    	     ApplicationContext ctx=new ClassPathXmlApplicationContext("beans2.xml");	 
    	     Boss boss=(Boss) ctx.getBean("childBoss");
    	     Set set=boss.getFavorites();
    	     System.out.println(set);
    	}
    运行后结果如下:
    [看报, 赛车, 高尔夫, 爬山, 游泳]










  • 相关阅读:
    WEB引入Google思源黑体
    Linux安装最新版Node.js
    JS判断值是否是数字
    高效jQuery的奥秘
    一个Web前端工程师或程序员的发展方向,未来困境及穷途末路
    javascript 模块化 (切记:学习思想)
    学习 正则表达式 js java c# python 通用
    Promise如何解决回调地狱
    VSCode 开发插件 推荐
    js移动端自适应动态设置html的fontsize
  • 原文地址:https://www.cnblogs.com/wuyida/p/6300369.html
Copyright © 2020-2023  润新知