2.5 导入和混合配置

[复制链接]
发表于 2024-8-12 11:09:01 | 显示全部楼层 |阅读模式

在典型的Spring应用中,我们可能会同时使用自动化和显式配置。即便你更喜欢通过JavaConfig实现显式配置,但有的时候XML却是最佳的方案。 幸好在Spring中,这些配置方案都不是互斥的。你尽可以将JavaConfig的组件扫描和自动装配和/或XML配置混合在一起。实际上,就像在2.2.1小节中所看到的,我们至少需要有一点显式配置来启用组件扫描和自动装配。 关于混合配置,第一件需要了解的事情就是在自动装配时,它并不在意要装配的bean来自哪里。自动装配的时候会考虑到Spring容器中所有的bean,不管它是在JavaConfig或XML中声明的还是通过组件扫描获取到的。 你可能会想在显式配置时,比如在XML配置和Java配置中该如何引用bean呢。让我们先看一下如何在JavaConfig中引用XML配置的bean。

2.5.1 在JavaConfig中引用XML配置

现在,我们临时假设CDPlayerConfig已经变得有些笨重,我们想要将其进行拆分。当然,它目前只定义了两个bean,远远称不上复杂的Spring配置。不过,我们假设两个bean就已经太多了。 我们所能实现的一种方案就是将BlankDisc从CDPlayerConfig拆分出来,定义到它自己的CDConfig类中,如下所示:

package soundsystem;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDConfig {
  @Bean
  public CompactDisc compactDisc() {
   return new SgtPeppers();
  }
}

compactDisc()方法已经从CDPlayerConfig中移除掉了,我们需要有一种方式将这两个类组合在一起。一种方法就是在CDPlayerConfig中使用@Import注解导入CDConfig:

package soundsystem;
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中使用@Import,而是创建一个更高级别的SoundSystemConfig,在这个类中使用@Import将两个配置类组合在一起:

package soundsystem;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({CDPlayerConfig.class, CDConfig.class})
public class SoundSystemConfig {
}

不管采用哪种方式,我们都将CDPlayer的配置与BlankDisc的配置分开了。现在,我们假设(基于某些原因)希望通过XML来配置BlankDisc,如下所示:

<bean id="compactDisc"
    class="soundsystem.BlankDisc"
    c:_0="Sgt. Pepper's Lonely Hearts Club Band"
    c:_1="The Beatles">
  <constructor-arg>
   <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>
    <!-- ...other tracks omitted for brevity... -->
   </list>
  </constructor-arg>
</bean>

现在BlankDisc配置在了XML之中,我们该如何让Spring同时加载它和其他基于Java的配置呢? 答案是@ImportResource注解,假设BlankDisc定义在名为cd-config.xml的文件中,该文件位于根类路径下,那么可以修改SoundSystemConfig,让它使用@ImportResource注解,如下所示:

package soundsystem;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
}

两个bean——配置在JavaConfig中的CDPlayer以及配置在XML中BlankDisc——都会被加载到Spring容器之中。因为CDPlayer中带有@Bean注解的方法接受一个CompactDisc作为参数,因此BlankDisc将会装配进来,此时与它是通过XML配置的没有任何关系。 让我们继续这个练习,但是这一次,我们需要在XML中引用JavaConfig声明的bean。

2.5.2 在XML配置中引用JavaConfig

假设你正在使用Spring基于XML的配置并且你已经意识到XML逐渐变得无法控制。像前面一样,我们正在处理的是两个bean,但事情实际上会变得更加糟糕。在被无数的尖括号淹没之前,我们决定将XML配置文件进行拆分。 在JavaConfig配置中,我们已经展现了如何使用@Import和@ImportResource来拆分JavaConfig类。在XML中,我们可以使用import元素来拆分XML配置。 比如,假设希望将BlankDisc bean拆分到自己的配置文件中,该文件名为cd-config.xml,这与我们之前使用@ImportResource是一样的。我们可以在XML配置文件中使用<import>元素来引用该文件:

<?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](http://www.springframework.org/schema/beans/spring-beans.xsd)">
  <import resource="cd-config.xml" />
  <bean id="cdPlayer"
     class="soundsystem.CDPlayer"
     c:cd-ref="compactDisc" />
</beans>

现在,我们假设不再将BlankDisc配置在XML之中,而是将其配置在JavaConfig中,CDPlayer则继续配置在XML中。基于XML的配置该如何引用一个JavaConfig类呢? 事实上,答案并不那么直观。<import>元素只能导入其他的XML配置文件,并没有XML元素能够导入JavaConfig类。 但是,有一个你已经熟知的元素能够用来将Java配置导入到XML配置中:<bean>元素。为了将JavaConfig类导入到XML配置中,我们可以这样声明bean:

<?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](http://www.springframework.org/schema/beans/spring-beans.xsd)">
  <bean class="soundsystem.CDConfig" />
  <bean id="cdPlayer"
     class="soundsystem.CDPlayer"
     c:cd-ref="compactDisc" />
</beans>

采用这样的方式,两种配置——其中一个使用XML描述,另一个使用Java描述——被组合在了一起。类似地,你可能还希望创建一个更高层次的配置文件,这个文件不声明任何的bean,只是负责将两个或更多的配置组合起来。例如,你可以将CDConfig bean从之前的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"
  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](http://www.springframework.org/schema/beans/spring-beans.xsd)">
  <bean class="soundsystem.CDConfig" />
  <import resource="cdplayer-config.xml" />
</beans>

不管使用JavaConfig还是使用XML进行装配,我通常都会创建一个根配置(root configuration),也就是这里展现的这样,这个配置会将两个或更多的装配类和/或XML文件组合起来。我也会在根配置中启用组件扫描(通过context:component-scan或@ComponentScan)。你会在本书的很多例子中看到这种技术。

GMT+8, 2025-6-6 23:18 , Processed in 0.065943 second(s), 33 queries Archiver|手机版|小黑屋|Attic ( 京ICP备2020048627号 )

快速回复 返回顶部 返回列表