我的应用程序可以在不同的环境中运行。我需要为每个环境配置MY数据模型。数据模型使用Spring bean构建。
我使用的是Spring 3.0.5,因此无法有条件地加载资源。 我有这个:
<bean id="Template1" class="...
..............
</bean>
<bean id="Template2" class="...
..............
</bean>
<bean id="Template3" class="...
..............
</bean>
................
<bean id="Factory" ...>
<propety name="type"><value>${app.type}</value></property>
<property>
<map>
<entry key="Temlate1" value-ref="Template1">
<entry key="Temlate2" value-ref="Template1">
<entry key="Temlate3" value-ref="Template1">
..................
我在工厂创建的真正的bean:
<bean id="real" factory="Factory" factory-method="getInstance"
<constructor-arg>Factory</.....
.............
</bean>
Java代码:
class Factory {
private Map<String, Object> templateBeans;
Object getInstance(String name) {
return templateBeans.get(name);
...........
是否有可能以某种方式声明抽象模板bean?因为我对记忆有很大的问题。是否有另一种方法可以在版本3.1之前的Spring中有条件地实例化不同的bean?最好只使用EL,因为我无法访问bean的Java代码,因为它们来自第三方库。
答案 0 :(得分:5)
我没有尝试过,但我相当确定你可以使用bean别名。
首先将所有模板bean声明为lazy,这样它们就不会在启动时实例化。
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
然后使用带有变量的bean别名指向真实的:
<alias name="real" alias="${beanForEnvironment}"/>
请参阅我的答案,了解如何很好地加载每个环境的属性:
答案 1 :(得分:1)
我之前遇到过这个问题并且为了解决它,我使用了Spring导入标记。例如:
<import resource="file:/location/to/your/config/my_beans.xml"/>
这允许您从应用程序war / jar外部化Spring XML配置。因此,在您的情况下,您将不得不为每个环境部署不同的外部Spring XML配置,但这也允许您实例化所需的确切bean。
答案 2 :(得分:0)
如果可能的话,一个干净的解决方案是不使用Factory,但是为不同的环境使用不同的配置文件,所有这些都定义了相同的“真正的”bean,但具有不同的实现。然后,在运行时,您只需导入正确的版本,例如模板。$ {app.type} .XML。
另一个更丑陋的解决方案是使模板bean成为lazy-init bean,并确保它们是动态创建的。你不能将它们注入工厂的地图中,因为无论如何都会将它们实例化。您可以存储beanNames的映射,并生成Factory ApplicationContextAware。然后在getInstance()方法中返回applicationContext.getBean(beanNames.get(...));
更复杂的解决方案是将XML配置与Spring JavaConfig混合使用,它允许您在bean定义中使用各种逻辑。
答案 3 :(得分:0)
如果您能够升级到Spring 3.1,它会为您提供profies
如果无法升级,请查看使用system variables(例如$ {ENV_SYSTEM:dev})在配置(属性)之间切换。
另一个好的SO是Common strategies when defining Spring beans for different environments
e.g。让你在service-development.xml
中使用开发bean,将其导入为:
<import resource="service-${profile}.xml"/>
并以-Dprofile=development
开头。或者当您进入QA时:-Dprofile=qa
答案 4 :(得分:0)
使用lazy init lazy-init="true"
但是也许bean会在Map中引用一次实例化,因此请使用带有实例名称的String Map,以便工厂通过代码向应用程序上下文请求它们。 context.getBean(MyInterface.class, templates.get(name));
答案 5 :(得分:0)
由于tolitius建议运行时参数工作得很好。您可以将-Dyourvar = yourvalue传递给java运行时,并且可以在spring导入中使用$ {yourvar}。如果未设置,那么您将从spring收到资源未找到错误。
如果它是一个独立的程序:java YourClass -Dyourvar = yourvalue 当您使用应用程序服务器时,您也可以设置运行时参数。搜索服务器文档,了解如何增加服务器内存。这个地方你可以设置-Xmx设置通常也是你可以设置-Dyourvar常数的地方。