Spring配置的混合使用

Spring配置的混合使用

在之前的文章中(Spring中的Bean装配|学习笔记 (syuez.com))讲了 Spring 的自动装配,但是有时候不得不使用 XML 配置。本文将简单介绍一下 Java 配置和 XML 配置混合使用的情景。

在之前定义的 SgtPeppers 唱片中只包含了唱片名称和艺术家的名字。如果现实世界中的 CD 也是这样的话,那么在技术上就不会任何的进展。CD 之所以值得购买是因为它上面所承载的音乐。大多数的 CD 都会包含十多个磁道,每个磁道上包含一首歌。

如果使用 CompactDisc 为真正的 CD 建模,那么它也应该有磁道列表的概念。请考虑下面这个新的 BlankDisc:

import java.util.List;

public class BlankDisc implements CompactDisc {

    private String title;
    private String artist;
    private List<String> tracks; // 磁道,CD 都会包含十多个磁道,每个磁道上包含一首歌

    public BlankDisc(String title, String artist, List<String> tracks) {
        this.title = title;
        this.artist = artist;
        this.tracks = tracks;
    }

    @Override
    public void play() {
        System.out.println("Playing " + title + " by " + artist);
        for (String track : tracks) {
            System.out.println("-Track: " + track);
        }
    }
}

这个变更会对 Spring 如何配置 bean 产生影响,在声明 bean 的时候,我们必须要提供一个磁道列表。最简单的办法是将列表设置为 null,将 null 传递给构造器。因为它是一个构造器参数,所以必须要声明它。

这并不是解决问题的好办法,虽然在注入期它能正常执行。但当调用 play() 方法时,你会遇到 NullPointerException 异常,因此并不是理想的方案。

更好的解决方法是提供一个磁道名称的列表。在 resources 目录中创建 Spring XML 配置文件 blank-disc.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="blankDisc" class="com.syuez.BlankDisc" primary="true">

        <constructor-arg index="0" value="Sgt. Pepper's Lonely Hearts Club Band" />
        <constructor-arg index="1" value="The Beatles" />
        <constructor-arg index="2">
            <list>
                <value>Sgt. Pepper's Lonely Hearts Club Band</value>
                <value>With a Little Help from My Friends</value>
                <value>Lucy in the Sky with Diamonds</value>
                <value>Getting Better</value>
                <value>Fixing a Hole</value>
            </list>
        </constructor-arg>
    </bean>

</beans>

由于此处存在多个符合 CDPlayer 自动注入的 CompactDisc 类,所以添加了 primary 标签来标示首选的 bean。

接着要使 blank-disc.xml 生效,在 CDPlayerConfig 中添加 @ImportResource 注解:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
/**
 * CD配置类
 */
@Configuration
@ComponentScan
@ImportResource({"classpath*:blank-disc.xml"})
public class CDPlayerConfig {
}

重新运行 CDPlayerTest 测试,看是否通过


参考链接:

Spring 自动装配,Java 配置,XML配置、混合使用 - 程序员文章站 (superweb999.com)

Spring @ImportResource Annotation Example (javaguides.net)

详解Spring项目中的classpath路径_Allen Chou的博客-CSDN博客_spring获取classpath路径

What is the alternative of using @Qualifier annotation in XML in Spring? - Stack Overflow

Java / Spring: "Tagging" beans in XML to get specific bean by class and tag - Stack Overflow