在 Spring 中多种配置方案不是互斥的,可以混合使用。在混合配置时,自动配置并不在意要装配的 bean 来自哪里,它会考虑到 Spring 容器中的所有 bean,不管它是通过配置类、XML 配置文件或者组件扫描获取到的。
在配置类中引用 XML 配置
首先,分别创建 CompactDisc 接口及其实现类 SgtPeppers,Media 接口及其实现类 CDPlayer,BlankDisc,代码如下:
package org.example.mixconfig;
public interface CompactDisc {
void play();
}
package org.example.mixconfig;
public class SgtPeppers implements CompactDisc{
private String title = "Sgt. Pepper's Lonely Hearts Club Band";
private String artist = "The Beatles";
@Override
public void play() {
System.out.println("Playing " + title + " by " + artist);
}
}
package org.example.mixconfig;
public interface MediaPlayer {
void play();
}
package org.example.mixconfig;
public class CDPlayer implements MediaPlayer{
private CompactDisc cd;
public CDPlayer(CompactDisc cd){
this.cd = cd;
}
@Override
public void play() {
cd.play();
}
}
然后,定义一个 CDConfig 类,代码如下:
package org.example.mixconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDConfig {
@Bean
public CompactDisc compactDisc(){
return new SgtPeppers();
}
}
接着,创建一个 CDPlayerConfig 类,并使用 @Import 注解引入 CDConfig 类,代码如下:
package org.example.mixconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import(CDConfig.class) // 导入外部配置类
public class CDPlayerConfig {
@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
return new CDPlayer(compactDisc);
}
}
另外一种方式是不在 CDPlayerConfig 类中引入 CDConfig 类,而是使用 @Import 注解将这两个配置类组合到一个更高级别的配置类中,代码如下:
package org.example.mixconfig;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration
@Import({CDPlayerConfig.class, CDConfig.class}) // 导入外部配置类
public class SoundSystemConfig {
}
注意,这里因为 CDPlayerConfig 类、 CDConfig 类、SoundSystemConfig 类都在一个包中,所以省略了包路径,如果不在一个包中可以使用类的全限定路径。
如果我们通过 XML 来配置了 SgtPeppers 类时,配置文件名为 cd-config.xml,位于项目的类路径(resources 目录)下。配置如下:
<!--cd-config.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="compactDisc" class="org.example.mixconfig.SgtPeppers"/>
</beans>
可以使用 @ImportResource 注解在配置类中引入 XML 配文件中的配置:
package org.example.mixconfig;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
@ContextConfiguration
@Import(CDPlayerConfig.class) // 导入外部的配置类
@ImportResource("classpath:cd-config.xml") //导入外部的 XML 配置文件
public class SoundSystemConfig {
}
在 XML 配置中引用配置类
在 XML 配置文件中,我们可以使用 <import> 元素来拆分 XML 配置。例如,在cdplayer-config.xml 配置文件中导入cd-config.xml配置文件,代码如下:
<!--cdplayer-config.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">
<!--导入外部的 XML 配置文件-->
<import resource="classpath:cd-config.xml"/>
<bean id="cdPlayer" class="org.example.mixconfig.CDPlayer">
<constructor-arg ref="compactDisc"/>
</bean>
</beans>
另外,还可以在 XML 配置中导入外部的配置类,例如,将前面的 CDConfig 配置类导入到cdplayer-config.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">
<!--在 XML 中导入外部的配置类-->
<bean class="org.example.mixconfig.CDConfig"/>
<bean id="cdPlayer" class="org.example.mixconfig.CDPlayer">
<constructor-arg ref="compactDisc"/>
</bean>
</beans>
配置类和 XML 配置文件可以组合起来使用。不管使用配置类还是 XML 配置文件,通常都会创建一个根配置,这个配置将两个或者多个配置类/XML配置文件组合起来,在根配置中开启组件扫描(通过<context:component-scan> 或 @ComponentScan)。