XML 装配

新项目不怎么用了XML 来进行配置了,但是在对老项目进行维护时,还是需要的。

在resource 中新建Spring XML 文件,我们一般把这个文件命名为ApplicaContext。

<?xml version="1.0" encoding="UTF-8"?>
<!-- 我们一般根据需要在下方声明xml 命名空间,或者xsd 文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 这里的Bean元素就相当于注解当中的@Bean,id属性可以被替换为name属性,二者都是给类命名的作用,不同的是,name属性可以给Bean元素起多个名字 name="daf sdf;sdf,dfa" 中间用空格、分号、逗号分隔。-->
    <bean id="service" class="hello.MessageService"></bean>
    <bean id="printer" class="hello.MessagePrinter">
        <property name="messageService" ref="service"></property>
    </bean>
</beans>

这里有对bean元素的详细说明,包括使用方法

依赖注入

  • 注入方式有3 中
  • 构造函数注入
  • c-名称空间注入
  • <property> 属性注入
  • p-名称空间注入(在最后面)
构造函数注入
  • <constructor-arg>元素
  • 需要有一个有参数的构造函数,之后再配置<constructor-arg>元素,<constructor-arg>元素是对构造函数中参数的注入,没有相应的构造函数则不能使用<constructor-arg>(可以改一下构造函数中参数的类型来验证一下,自己去试)
public MessagePrinter(MessageService messageService) {
this.messageService = messageService;
}
<bean name="service" class="hello.MessageService">
</bean>

<bean id="printer" class="hello.MessagePrinter">
<!-- 这里的ref 指定的就是将哪个个Bean对象传给相应的有参构造函数-->
<constructor-arg ref="service"/>
</bean>
c-名称空间,同样需要有参构造函数,这里同样使用上面刚提到的构造函数。
  • 首先需要在XML 文件中引入c 的名称空间,和其他的xmlns 放在一起就可以
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean name="service" class="hello.MessageService">
</bean>

<bean id="printer" class="hello.MessagePrinter" c:messageService-ref="service">
    <!-- 也可以是c:_0-ref="service" c 表示命名空间,_0表示参数在参数列表中的位置 -ref表示依赖注入,后面的字符串就是被注入的Bean 对象-->
</bean>
</beans>
<property> 属性

<property> 是对成员属性的注入,需提前设置set 函数,建议直接 Alt + Ins 生成默认的set 函数

<bean id="printer" class="hello.MessagePrinter" c:_0-ref="service">
    <property name="word" value="i love you"/>
    <!-- 如果注入目标是复杂数据类型,将value 换为ref,并提前设置被 “ref”对象的Bean-->
</bean>

这里需要说明,<property> 中的name 不是值成员变量的名字,而是类属性的名字。

属性的定义规则是:set/get方法名,去掉set/get后,将剩余部分首字母小写得到的字符串就是这个类的属性。这里的set/get方法指的是set/get 成员变量的函数。下面是一个例子

// userDao 是成员变量 
// setUserDao 的方法名可以修改为setAAAA,对应的属性名变为aAAA。
// 参数不能多也不能少,且类型一定要和成员变量对应
public void setUserDao(UserDao userDao) {
    // 这里可以添加自己的代码,但是下面这行代码不能删
        this.userDao = userDao;
}

public UserDao getUserDao() {
    return userDao;
}

各种数据类型的注入

  • 简单类型的数据注入,String,注意在对应类中要有相应的构造函数。
<?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:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="printer" class="hello.MessagePrinter">
    <!-- 注意这里有三种方式-->
    
    <!-- 第一种-->
    <!--<constructor-arg value="ligang"/>-->
    <!--<constructor-arg value="fanbinbin"/>-->
    
    <!--第二种-->
    <!--<constructor-arg name="brother" value="ligang"/>-->
    <!--<constructor-arg name="sister" value="fanbinbin"/>-->
    
    <!-- 第三种-->
    <constructor-arg index="0" value="ligang"/>
    <constructor-arg index="1" value="fanbinbin"/>
</bean>
</beans>

或者c-名称空间

<bean id="printer" class="hello.MessagePrinter" c:brother="ligang" c:sister="fanbinbin"/>

<!-- 或者 -->
<!-- <bean id="printer" class="hello.MessagePrinter" c:_0="ligang" c:_1="fanbingbing"/>-->
  • list 类型注入,list、set、map 都无法使用c-名称空间。
<bean id="printer" class="hello.MessagePrinter" c:_0-ref="service">
    <constructor-arg name = "list">
    	<list>
            <!-- 这里list中的元素是字符串 -->
            <value>i love you</value>
            <value>i love she</value>
            <!-- 像上面那样重复就可以-->
            <!-- 如果list 中的元素是复杂类型怎么办?-->
        </list>
    </constructor-arg>
</bean>

如果list 中的元素是复杂类型

<!-- 这里一定要对将要添加到list中的element元素添加Bean 元素-->
<bean id="element1" class="hello.word"></bean>
<bean id="element2" class="hello.word"></bean>
<bean id="element3" class="hello.word"></bean>
<bean id="printer" class="hello.MessagePrinter" c:_0-ref="service">
    <constructor-arg name = "list">
    	<list>
            <!--list 中元素为复杂类型时,不能再使用 value来添加元素-->
            <ref bean="element1"/>
            <ref bean="element2"/>
            <ref bean="element3"/>
            <!-- 像上面那样重复就可以-->
		</list>
    </constructor-arg>
</bean>

同样的,如果是对set 类型对象装入时,只需将<list> 换为 <set> 即可。

注意,set 中的元素时互异的,就是说无法添加两个完全相同的元素。本来set 也是无序的,但是这里默认使用的LinkHashSet,所以是有序的。

  • map 类型注入
<!-- 这里一定要对将要添加到list中的element元素添加Bean 元素-->
<bean id="element1" class="hello.word"></bean>
<bean id="element2" class="hello.word"></bean>
<bean id="element3" class="hello.word"></bean>
<bean id="printer" class="hello.MessagePrinter" c:_0-ref="service">
    <constructor-arg name = "map">
    	<map>
            <!--如果map 的value 值是String 的话,也可以直接用value-->
            <entry key="e1" value-ref="element1"/>
            <entry key="e1" value-ref="element1"/>
            <entry key="e1" value-ref="element1"/>
            <!-- 像上面那样重复就可以-->
		</map>
    </constructor-arg>
</bean>
  • 数组的注入,String[] 这种
<!-- 这里一定要对将要添加到list中的element元素添加Bean 元素-->
<bean id="element1" class="hello.word"></bean>
<bean id="element2" class="hello.word"></bean>
<bean id="element3" class="hello.word"></bean>
<bean id="printer" class="hello.MessagePrinter" c:_0-ref="service">
    <constructor-arg name = "array">
    	<array>
            <!--String[] 和基本数据类型的数组-->
            <value>i love you </value>
            
            <!--复杂数据类型的数组-->
            <ref bean="element1"/>
            <ref bean="element2"/>
            <ref bean="element3"/>
            <!-- 像上面那样重复就可以-->
		</array>
    </constructor-arg>
</bean>
  • 总结上面的代码,可以发现String 及基本数据类型赋值时用的都是value。而对复杂数据类型,使用的都是ref 或者-ref(reference:引用),并且都需要提前设置被 “ref”对象的Bean。这对下面的<property>配置同样适用。
  • <property>对数组、list、set、map数据类型的注入,与<constructor>的注入方式基本一致,这里只举一个例子。
<!-- 这里一定要对将要添加到list中的element元素添加Bean 元素-->
<bean id="element1" class="hello.word"></bean>
<bean id="element2" class="hello.word"></bean>
<bean id="element3" class="hello.word"></bean>
<bean id="printer" class="hello.MessagePrinter" c:_0-ref="service">
    <property name = "array">
    	<array>
            <!--String[] 和基本数据类型的数组-->
            <value>i love you </value>
            
            <!--复杂数据类型的数组-->
            <ref bean="element1"/>
            <ref bean="element2"/>
            <ref bean="element3"/>
            <!-- 像上面那样重复就可以-->
		</property>
    </constructor-arg>
</bean>
  • 还可以使用p 名称空间注入。数组、list、set、map数据类型的注入不能使用p 名称空间
  • p 名称空间同样需提前设置set 函数。
<!-- 首先在上方添加p 命名空间,具体语句如下-->
<!--xmlns:c="http://www.springframework.org/schema/c"-->

<bean id="printer" class="hello.MessagePrinter" p:brother="XiaoGeGe">
    <!-- 如果注入目标是复杂数据类型,将value 换为-ref,并提前设置被 “ref”对象的Bean-->
</bean>
  • 要想使用p 名称空间注入数组、list、set、map,需要结合使用util
  • util 的名称空间声明挺复杂,可以直接在下面输入<util:list>,然后让idea 自己为我们导入

数组、List数据类都是使用的都是util:list

set、map使用的分别是util:set、util:map

<util:list name="littlelist">
        <ref bean="element1"/>
        <ref bean="element2"/>
        <ref bean="element3"/>
    </util:list>
<!-- 之后在下面的bean 节点中添加p 节点。-->
<bean id="printer" class="hello.MessagePrinter" p:list="littlelist"></bean>