想象一下具有不同阶段的分阶段应用程序上下文。我们从早期阶段开始定义必要的基础结构。xml应用程序上下文按顺序加载。
拆分这些文件的原因是扩展/插件机制。
阶段01-default-configuration.xml
我们准备并声明具有ID的地图,exampleMapping以在以后使用数据对其进行增强。
exampleMapping
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="[...]"> <util:map id="exampleMapping" /> </beans>
阶段02-custom-configuration.xml (可选)
我们配置exampleMapping并添加一个条目。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="[...]"> <util:map id="exampleMapping"> <entry key="theKey" value="theValue" /> </util:map> </beans>
阶段03-make-use-of-configuration.xml (强制性)
使用已定义的map exampleMapping,无论它是自定义配置的还是仍然是空的声明的map。
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="[...]"> <bean id="exampleService" class="com.stackoverflow.example.ExampleService"> <property name="mapping" ref="exampleMapping" /> </bean> </beans>
这里的问题是,exampleMapping在第一阶段之后无法将条目添加到地图。Spring抛出一个异常,即具有ID的地图exampleMapping已经存在。如果我们遗漏了第一阶段,则地图未声明,第三阶段无法解析exampleMapping,这也会产生异常。
我该如何解决这个问题?我读了Collection合并(春季文档),但这没有帮助。是否有可能在以后使用值之前在地图/列表中添加值?
谢谢!
您 可以 定义exampleMapping第二个定义在单独的文件中,并且您<import resource="..."/>可以将一个文件导入另一个文件,但这是一种脆弱的方法,很容易被破坏。
<import resource="..."/>
我建议采取更有效的策略。将其替换为exampleMapping一个Registry类,该类又包含并管理映射:
Registry
public MappingRegistry<K,V> { private final Map<K,V> mappings = new HashMap<K,V>(); public void addMapping(K key, V value) { mappings.put(key, value); } public Map<K,V> getMappings() { return Collections.unmodifiableMap(mappings); } }
然后,编写一个向注册表注册映射的类:
public class MappingRegistrar<K,V> { private final MappingRegistry<K,V> registry; private K key; private V value; @Autowired public MappingRegistrar(MappingRegistry<K,V> registry) { this.registry = registry; } public void setKey(K key) { this.key = key; } public void setValue(V value) { this.value = value; } @PostConstruct public void registerMapping() { registry.addMapping(key, value); } }
您的配置将如下所示:
<bean id="mappingRegistry" class="com.xyz.MappingRegistry"/> <bean id="mappingA" class="com.xyz.MappingRegistrar" p:key="keyA" p:value="valueA"/> <bean id="mappingB" class="com.xyz.MappingRegistrar" p:key="keyB" p:value="valueB"/> <bean id="mappingC" class="com.xyz.MappingRegistrar" p:key="keyC" p:value="valueC"/>
这些映射现在可以按照您认为合适的任何方式散布在您的配置中,并且它们将自动组装。 ExampleServcie然后向注入并相应地MappingRegistry提取映射。
ExampleServcie
MappingRegistry
它比您已经拥有的工作要多一些,但是它更加灵活并且不易出错。如果您要构建某种可扩展的框架,则这特别有价值。您希望对人们的使用方式施加更少的限制。