使用 Spring 时,将运行时数据合并到 bean 构造中是相当麻烦的。虽然有一些技术可以规避这种分离,但我觉得它是有原因的。我的问题是这是否是一个已知的范式,以及是否有任何文献讨论它。我个人发现它既有优点也有缺点,具体取决于应用程序的动态性。
问问题
321 次
2 回答
3
您至少有五个众所周知的方法可以将运行时数据传递给 bean 配置:
- 用于
ApplicationContextInitializer
添加PropertySources
到Enviroment
. - 使用 SPEL 注入依赖项。
- 利用
FactoryBeans.
- 使用
factory-bean
和factory-method
属性。 - 如果你编写需要运行时数据的类,你只需要注入提供它的协作者。
例如
<bean id="requestAttributeReader" class="example.RequestAttributeReader" />
<bean id="requestInjectedBean" class="example.RequestInjectedBean" scope="request">
<property name="a" value="#{requestAttributeReader.a}" />
</bean>
Class RequestAttributeReader {
public String getA() {
return RequestContextHolder.getAttributes().getAttribute("a");
}
}
编辑
IoC 容器的 bean 描述文件允许您在应用程序 bean 上配置实现器。这通常是您要用于具体配置的实现类的静态定义,因此 xml 对它有好处。
如果你需要根据运行时选择一个实现者,那么你需要编写代码来选择它们,然后通知容器。
例如,使用PropertySources
and PropertyPlaceholderConfigurer
:
String service = "example.NormalService";
if (BOSS_USERNAME.equals(System.getProperty("user.name")))
service = "example.BossService";
ctx.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("service", service));
<bean id="service" class="${service}" />
ServiceFactoryBean、外部 ServiceFactory、SPEL 等也可以这样做......
也许,您对在运行时替换实现感兴趣,即更改所有 bean 中的 Service 实现,这取决于容器何时刷新。(没有破坏和刷新)。
据我所知,该框架没有提供明确的方法来做到这一点。
于 2012-09-18T21:16:38.757 回答
2
听起来你应该看看弹簧绑定,例如:
public String create(@Valid Market market, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
因此,这将采用与 Market 对象中的字段匹配的请求参数并将它们设置在该对象中。它还将验证参数/对象,因为有 @Valid 注释。可以使用 PropertyEditors 或 Converters 自定义此绑定。
如果市场对象被注解为@Configurable,那么它可以在spring创建它时使用@Autowired和@Value注解来配置bean。
于 2012-09-19T00:30:03.173 回答