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属性进行覆盖默认装配策略。