在我的应用程序中,我使用ContextLoaderListener从许多jar加载上下文文件:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/contextBeans.xml</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)
这意味着我可以在不进行导入的情况下从其他jar中引用bean.
在应用程序中有多个部署选项,在某些部署中可以排除jar.为了支持我,我希望一些bean引用是可选的.例如:
<bean id="mainAppBean" class="com.someapp.MyApplication">
<constructor-arg index="0" ref="localBean"/>
<constructor-arg index="1" ref="optionalBeanReference1"/>
<constructor-arg index="2" ref="optionalBeanReference2"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我想如果找不到引用,则optionalBeanReference1等于null(以某种方式将其标记为可选)
这可以在Spring完成吗?或者您推荐哪种方法来处理动态参考?
Cri*_*bie 25
我最好的猜测是使用自动装配所需的假.不知道如何用XML表达它,但使用注释配置,它看起来像:
@Autowired(required=false)
Run Code Online (Sandbox Code Playgroud)
ase*_*ell 16
使用最新版本的Spring(使用Spring 4.1测试)和Java Configuration和Java 8,您可以在参数中使用Optional,并且只在可用时自动连接.
@Autowired
public MyApplication(Optional<YourOptionalObject> maybeObject) {
// do something with the optional autowired
}
Run Code Online (Sandbox Code Playgroud)
Gra*_*ray 10
您建议使用什么方法处理动态引用?
我认为@ cristian的@Autowired答案很好.如果该类型的bean可用,那将调用setter方法.但是,如果你有多个相同类型的bean,我相信Spring会抛出异常.如果由于这个或其他原因你不能使用@Autowired,我会看到几个解决方案:
您可以自己创建类ApplicationContextAware并在上下文中查找bean:
public void setApplicationContext(ApplicationContext applicationContext) {
if (applicationContext.containsBean("optionalBeanReference1")) {
setOptionalBeanReference1(
(OptionalBeanReference1)applicationContext.bean(
"optionalBeanReference1");
}
...
}
Run Code Online (Sandbox Code Playgroud)你可以反转依赖.每个可选类都可以在mainAppBean上设置自己.我在某些情况下使用它,直接依赖会导致循环或其他问题.
<bean id="optionalBeanReference1" class="com.someapp.SomeClass">
<constructor-arg index="0" ref="mainAppBean"/>
</bean>
Run Code Online (Sandbox Code Playgroud)
然后在SomeClass中:
public SomeClass(com.someapp.MyApplication mainAppBean) {
mainAppBean.setOptionalBeanReference1(this);
}
Run Code Online (Sandbox Code Playgroud)您可以保留直接依赖关系,然后导入一个定义了bean的文件,或者导入另一个文件,您可以使用工厂bean将bean定义为具有空值.请参阅此工厂代码.
祝好运.
这没有内置机制.但是,您可以编写一个非常简单的FactoryBean实现来为您执行此操作,如下所示:
public class OptionalFactoryBean extends AbstractFactoryBean<Object> implements BeanNameAware {
private String beanName;
@Override
public void setBeanName(String beanName) {
this.beanName = BeanFactoryUtils.originalBeanName(beanName);
}
@Override
protected Object createInstance() throws Exception {
if (getBeanFactory().containsBean(beanName)) {
return getBeanFactory().getBean(beanName);
} else {
return null;
}
}
@Override
public Class<?> getObjectType() {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它:
<bean id="mainAppBean" class="com.someapp.MyApplication">
<constructor-arg index="0" ref="localBean"/>
<constructor-arg index="1">
<bean name="optionalBeanReference1" class="com.someapp.OptionalBeanFactory"/>
</constructor-arg>
<constructor-arg index="2">
<bean name="optionalBeanReference2" class="com.someapp.OptionalBeanFactory"/>
</constructor-arg>
</bean>
Run Code Online (Sandbox Code Playgroud)
鉴于XML配置中的bean引用是通过表达式语言(EL)定义的,您可以执行以下操作:
<property name="cache" value="#{getObject('optionalCache')}" />
Run Code Online (Sandbox Code Playgroud)
它利用了这种BeanExpressionContext.getObject()方法.有关详细信息,请参见此处
| 归档时间: |
|
| 查看次数: |
30507 次 |
| 最近记录: |