通过不同的string文本来生成/获取不同的service。
有的时候我们需要通过客户端传入的文本,例如actionCode,来调用不同的service, 在没有使用spring之前,一般是创建一个工厂,然后通过不同的string来创建不同的service。
例如
if(actionCode.equals(A)){
new AServiceImpl();
}else if(actionCode.equals(B)){
new BServiceImpl();
}
注意AServiceImpl和BServiceImpl都实现相同的接口IService。
上面的这种实现,在service中如果依赖其他的servcie时,会比较麻烦,而且如果有新的service需要更改这个factory。不利于扩展。
在使用spring的项目中,对应这种需求,我们有更好的实现方式,方法如下:
1. 在IService 增加一个方法,例如 public boolean support(@Nonnull String actionCode)
2. 每个service实现在这个方法,当actionCode是需要该service处理时,返回true,如:
AServiceImpl的support方法如下:
public boolean support(@Nonnull String actionCode) {
return StringUtils.equals(“delete”, actionCode);
}
3. 在spring注册上面的service
4. 实现factory, 代码如下:
public class IServiceBeanFactory {
private static final Logger LOG = LoggerFactory.getLogger(IServiceBeanFactory.class);
//默认的service
private static final IService DEFAULT_SERVICE = new DefaultServiceImpl();
//缓存service
private static final Map<String, IService> SERVICES_CACHE = new ConcurrentHashMap<String, IService>();
@Nonnull
public static IService getService(@Nonnull String actionCode){
IService existedHanlder = SERVICES_CACHE.get(actionCode);
if(existedHanlder != null){
return existedHanlder;
}
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
Collection<IService> handlers = context.getBeansOfType(IService.class).values();
for (Iterator<IService> iterator = handlers.iterator(); iterator.hasNext(); ) {
IService bean = iterator.next();
if((!bean.getClass().isAssignableFrom(DefaultServiceImpl.class)) && bean.support(actionCode)){
SERVICES_CACHE.put(actionCode, bean);
return bean;
}
}
return DEFAULT_SERVICE;
}
}
这种实现方式的好处,当有新的service时,只需要实现Iservice接口,然后到spring中注册一下即可。
同时往这些service注入相关的其他servce也更容易(spring中使用ref)。