Spring是否允许在非抽象中转换抽象bean?

时间:2011-10-28 21:51:48

标签: java spring javabeans

我的应用程序可以在不同的环境中运行。我需要为每个环境配置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代码,因为它们来自第三方库。

6 个答案:

答案 0 :(得分:5)

我没有尝试过,但我相当确定你可以使用bean别名。

首先将所有模板bean声明为lazy,这样它们就不会在启动时实例化。

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>

然后使用带有变量的bean别名指向真实的:

<alias name="real" alias="${beanForEnvironment}"/>

请参阅我的答案,了解如何很好地加载每个环境的属性:

property-placeholder location from another property

答案 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常数的地方。