Spring的核心文件是applicationContext.xml文件。

用spring的时候需要一个bean容器来管理所有的bean,所有bean默认是写在applicationContext.xml里的。

当然如果是几个人同时合作完成一个工程的话,也可以每人有一个xml的配置文件,最后在applicationContext.xml一起引入即可。



我们知道,一个web工程自动加载的配置文件只有web.xml,想要加载其他.xml必须在web.xml里面进行配置。Spring的applicationContext.xml也不例外。

下面是一个典型的使用的spring的web工程的web.xml的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">

<!-- Spring配置 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 指定Spring Bean的配置文件所在目录。默认配置在WEB-INF目录下 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>

<!-- 欢迎界面,这个可以自己设置 -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

</web-app> 


注意:<context-param>是可选项,如果没有的话就加载applicationContext.xml,也可以用它指定其他配置文件。


说完了基础的配置,我们回到正题,我们可以在applicationContext.xml文件中使用<bean>元素定义Bean以及使用<constructor-arg>(通过构造器注入)或<property>元素(配置属性,通过setxx方法)来装配Bean。举个例子如下:

一个简单的Bean

class HelloBean{
    private String name;
    private int number;
    private Date date;
    
    public HelloBean(Date date, String name, int number) {
        this.date = date;
        this.name = name;
        this.number = number;
      }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**  
     * @param name the name to set  
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the number
     */
    public int getNumber() {
        return number;
    }

    /**  
     * @param number the number to set  
     */
    public void setNumber(int number) {
        this.number = number;
    }

    /**
     * @return the date
     */
    public Date getDate() {
        return date;
    }

    /**  
     * @param date the date to set  
     */
    public void setDate(Date date) {
        this.date = date;
    }
    
}




applicationContext.xml文件中:

用构造器注入:

<beans>
   <bean id="helloBean" class="com.yangsq.spring.HelloBean">
      <!-- 构造器注入 -->
      <constructor-arg index="0">
          <bean class="java.util.Date"/>
      </constructor-arg>
      <constructor-arg index="1">
          <value>yangsq</value>
      </constructor-arg>
      <constructor-arg index="2">
          <value>123</value>
      </constructor-arg>
   </bean>
</beans>

属性注入:

<beans>
   <bean id="helloBean" class="com.yangsq.spring.HelloBean">
      <!-- 属性注入 -->
      <property name="date">
          <bean class="java.util.Date"/>
      </property>
      <property name="name" value="zhu">
      </property><pre name="code" class="html"><property name="number" value="123">    
      </property>
   </bean>
</beans>





这对于只包含少量的Bean的应用来说,很不错。但如果应用比较复杂,Bean很多时,这个xml文件就很庞大了。当然你也可以像最上面截图里那样,分开写,每个人写一部分最后合起来。Spring为了帮助解决这个这个问题,提供了两种很强大的技巧,自动装配和自动检测。下面分别来看看它们的作用:

自动装配:用于减少<constructor-arg>或<property>元素的使用,让Spring自动识别如何装配Bean的依赖关系

自动检测:比自动装配更进一步,让Spring能够自动识别哪些类需要被配置成Spring Bean,减少<bean>元素的使用。

Spring提供了四种类型的自动装配,可以通过把bean的“autowire”设置成它们来完成自动装配,它们分别是:

1.byName:把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的名字相匹配的Bean,则该属性不进行装配。

举个例子,

<beans>
   <bean id="date" class="java.util.Date">
   <bean id="helloBean" class="com.yangsq.spring.HelloBean" autowire="byName">
      <!-- 属性注入 -->
      <property name="name" value="zhu">
      </property>
      <property name="number" value="123">    
      </property>
   </bean>
</beans>

我添加了一个日期Bean,id为“date”,这个id与helloBean的“date”属性的名字是一样的。通过配置autowire属性,Spring就利用这个信息自动装配了helloWorld的date属性。可以明显看到,在helloBean中少了一组property属性。


2.byType:把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的类型相匹配的Bean,则该属性不进行装配。

注意:由于是按照类型匹配,难免会出现有多个bean的类型都与需要自动装配的属性的类型匹配的情况,此时Spring不会猜测哪一个bean更适合自动装配,而是会抛出异常。

为了解决上述问题,Spring提供了两个选择:

1)可以为自动装配标识一个首选bean。

<bean id="date" class="java.util.Date" primary="false">

由于primary属性默认为true,为了产生首选bean,我们不得不将所有非首选bean的primary设为false。

2)可以取消某个bean自动装配的候选资格。

<bean id="date" class="java.util.Date" autowire-candidate="false">



3.constructor自动装配

用来移除<constructor-arg>元素,但它与byName有相同的局限性。当发现多个bean匹配某个构造器的入参时,Spring不会猜测哪个更合适。


4.autodetect,最佳自动装配,先尝试用constructor进行自动装配,如果失败,再用byType。


如果要为Spring应用上下文中每一个bean配置相同属性,可以在根元素<beans>上增加一个default-autowire属性:<beans default-autowire="byType">

当然,如有特殊的,可以用<bean>元素的autowire属性进行覆盖默认装配策略。