根据传递给方法的参数,我需要从许多 Spring bean 中选择一个,它们是同一个类的实现,但配置了不同的参数。
例如,如果用户 A 调用该方法,我需要调用dooFoo()
bean A,但如果是用户 B,那么我需要调用相同的方法,仅在 bean B 上。
除了将所有bean粘贴在地图中并从传递给我的方法的参数中派生密钥之外,是否还有一种“Springier”方式来执行此操作?
我们在项目中遇到了这个问题,我们通过类似工厂的类来解决它。客户端类——在运行时需要 bean——有一个工厂的实例,它是通过 Spring 注入的:
@Component
public class ImTheClient{
@Autowired
private ImTheFactory factory;
public void doSomething(
Parameters parameters) throws Exception{
IWantThis theInstance = factory.getInstance(parameters);
}
}
因此,IWantThis
实例取决于parameters
参数的运行时值。工厂实现是这样的:
@Component
public class ImTheFactoryImpl implements
ImTheFactory {
@Autowired
private IWantThisBadly anInstance;
@Autowired
private IAlsoWantThis anotherInstance;
@Override
public IWantThis getInstance(Parameters parameters) {
if (parameters.equals(Parameters.THIS)) {
return anInstance;
}
if (parameters.equals(Parameters.THAT)) {
return anotherInstance;
}
return null;
}
}
因此,工厂实例包含对类的两个可能值的引用,即IWantThis
存在IWantThisBadly
和.IAlsoWantThis
IWantThis
似乎您想要ServiceLocator
使用应用程序上下文作为注册表。
请参阅ServiceLocatorFactoryBean支持类以创建将键映射到 bean 名称的 ServiceLocators,而无需将客户端代码耦合到 Spring。
其他选项是使用命名约定或基于注释的配置。
例如,假设您使用 注释服务@ExampleAnnotation("someId")
,您可以使用类似以下服务定位器的内容来检索它们。
public class AnnotationServiceLocator implements ServiceLocator {
@Autowired
private ApplicationContext context;
private Map<String, Service> services;
public Service getService(String id) {
checkServices();
return services.get(id);
}
private void checkServices() {
if (services == null) {
services = new HashMap<String, Service>();
Map<String, Object> beans = context.getBeansWithAnnotation(ExampleAnnotation.class);
for (Object bean : beans.values()) {
ExampleAnnotation ann = bean.getClass().getAnnotation(ExampleAnnotation.class);
services.put(ann.value(), (Service) bean);
}
}
}
}
把它们贴在地图上听起来不错。如果它是 Spring 管理的映射(使用util:map
或在 Java 配置中),那比在其他地方创建它要好,因为 Spring 拥有所有对象引用并可以正确管理它们的生命周期。
如果你说的豆子(A,B)完全SessionScope
没有问题,它们将被正确选择。
public class BusinessLogic {
private BaseClassOfBeanAandB bean;
public void methodCalledByUserAorB() {
bean.doFoo();
}
}