我有一个由2个模块组成的应用程序。
其中第一个是主要的,它可以在没有安装第二个模块的情况下工作。
我的bean在主模块的beans.xml
文件中定义了默认实现。当安装第二个模块时,我想保留这些bean的id,但是改变实现以使用新类。
最好的方法是什么?
第一个模块的 beans.xml
:
...
<bean id="myCoolService" class="com.blabla.defaultCoolServiceImpl">
...
在安装第二个模块之后,我想使用第二个模块中定义的myCoolService
的实现。
UPD: Spring版本是3.2.4。 我需要做尽可能少的更改,所以我需要继续使用xml驱动的配置。
答案 0 :(得分:1)
实现此目的的一种方法是通过代理,重定向到正确的实现。代理通常会重定向到默认值。如果模块2可用,它将重定向到模块2。
为了帮助代理找出可用的内容,您可能需要
始终使用&#34; name&#34;指向默认实现的成员属性。
有一种方法可以将另一个bean注册为备用实现。
例如
MyProxy内部:
@Autowired
public void setDefaultWorker(Worker defaultWorker) {
this.defaultWorker = defaultWorker;
}
private Worker defaultWorker;
private Worker alternateWorker;
public void registerAlternateWorker(Worker alternateWorker) {
this.alternateWorker = alternateWorker;
}
//To use the worker
private Worker getWorker() {
return alternateWorker == null? defaultWorker : alternateWorker;
}
在第1单元中,您的默认实现bean应声明为具有defaultWorker作为名称
<bean id="defaultWorker" class="MyDefaultWorkerImpl"/>
模块2可以在启动时使用SmartLifeCycle将自己注册到代理注册表。
答案 1 :(得分:1)
这样做的一种方法是引入一个通用接口(我猜一个应该已经存在):
public interface MyInterface {
//...
}
然后在主模块中使用@Service
@Service
public class DefaultImplementation implements MyInterface {
//...
}
然后,如果您的某个模块需要覆盖此实现,请使用@Primary
- 注释:
@Service
@Primary
public class OverridingImplementation implements MyInterface {
//...
}
然后,以下代码:
@Inject
private MyInterface myInterface;
如果未扫描DefaultImplementation
,将注入OverridingImplementation
,如果扫描,则会注入OverridingImplementation
(不会抱怨多个bean)。
答案 2 :(得分:0)
如果可能,请使用:
<bean id="myCoolService" class="${IMPL_CLASS_NAME}"/>
在属性文件中定义impl类。
IMPL_CLASS_NAME=com.blabla.SecondMduleCoolServiceImpl
或其他方法可能是:
让我们说你的defaultCoolServiceImpl和SecondMduleCoolServiceImpl实现了ICoolService接口
您可以定义这些bean和FactoryBean的实现,如下所示:
<bean id="mydefaultServiceimpl" class="com.blabla.defaultCoolServiceImpl">
<bean id="secondModuleCoolserviceimpl" class="com.blabla.SecondMduleCoolServiceImpl">
<bean id="myCoolService" class="com.blabla.ImplSelector"/>
public class ImplSelector implements FactoryBean<ICoolService>, ApplicationContextAware {
private ApplicationContext iApplicationContext;
// @Value("#{corePropertyConfigurer['defaultOrCool']}") you can injcet via property file.
private String defaultOrCool = "cool" ;
@Override
public ICoolService getObject() throws Exception {
if (StringUtils.equals(defaultOrCool, "default")) {
return iApplicationContext.getBean("mydefaultServiceimpl", ICoolService.class);
}
return iApplicationContext.getBean("secondModuleCoolserviceimpl", ICoolService.class);
}
@Override
public Class<?> getObjectType() {
return ICoolService.class;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
iApplicationContext = applicationContext;
}
}
然后你可以通过autowiring或applicationContext.getBean访问myCoolService(&#34; myCoolService&#34;,ICoolService.class);