java 如何在运行时选择 Spring bean 实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17702031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I select Spring bean instance at runtime
提问by EngineerBetter_DJ
Based on parameters passed to a method, I need to select from one of many Spring beans that are implementations of the same class, but configured with different parameters.
根据传递给方法的参数,我需要从许多 Spring bean 中选择一个,这些 bean 是同一类的实现,但配置了不同的参数。
E.g. if user A invokes the method, I need to call dooFoo()
on bean A, but if it's user B then I need to call the very same method, only on bean B.
例如,如果用户 A 调用该方法,我需要调用dooFoo()
bean A,但如果它是用户 B,那么我需要调用完全相同的方法,仅在 bean B 上。
Is there a 'Springier' way of doing this other than sticking all the beans in a map, and deriving a key from the parameters passed to my method?
除了将所有 bean 粘贴在地图中并从传递给我的方法的参数中派生出一个键之外,是否还有一种“Springier”的方法可以做到这一点?
采纳答案by Jose Luis Martin
Seems like do you want a ServiceLocator
using the application context as registry.
似乎您想要ServiceLocator
使用应用程序上下文作为注册表。
See ServiceLocatorFactoryBeansupport class for creating ServiceLocators mapping keys to bean names without coupling client code to Spring.
请参阅ServiceLocatorFactoryBean支持类以创建 ServiceLocator 将键映射到 bean 名称,而无需将客户端代码耦合到 Spring。
Other option is to use a naming convention or annotation based configuration.
其他选项是使用命名约定或基于注释的配置。
for example, assuming that you annotate Services with @ExampleAnnotation("someId")
, you can use something like the following Service Locator to retrieve them.
例如,假设您使用 注释服务@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);
}
}
}
}
回答by Carlos Gavidia-Calderon
We face that issue in our project, and we solve it through a Factory-Like class. The client class -the one that needed the bean at runtime- had an instance of the factory, that was injected through Spring:
我们在项目中遇到了这个问题,我们通过一个类似工厂的类来解决它。客户端类——在运行时需要 bean 的类——有一个工厂实例,它是通过 Spring 注入的:
@Component
public class ImTheClient{
@Autowired
private ImTheFactory factory;
public void doSomething(
Parameters parameters) throws Exception{
IWantThis theInstance = factory.getInstance(parameters);
}
}
So, the IWantThis
instance depends on the runtime value of the parameters
parameter. The Factory implementation goes like this:
因此,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;
}
}
So, the factory instance holds reference to both of the posible values of the IWantThis
class, being IWantThisBadly
and IAlsoWantThis
both implementations of IWantThis
.
因此,工厂实例保存参照这两个的更多钞票值IWantThis
类,幸福IWantThisBadly
和IAlsoWantThis
的两个实现IWantThis
。
回答by artbristol
Sticking them in a map sounds fine. If it's a Spring-managed map (using util:map
, or in Java config), that's better than creating it somewhere else, because then Spring owns all the object references and can manage their lifecycle properly.
把它们贴在地图上听起来不错。如果它是 Spring 管理的映射(使用util:map
,或在 Java 配置中),那比在其他地方创建它更好,因为这样 Spring 拥有所有对象引用并且可以正确管理它们的生命周期。
回答by Manuel
If the beans (A, B) you are talking about are SessionScope
its no problem at all, they will be selected correctly.
如果你所说的豆子(A,B)SessionScope
完全没有问题,它们将被正确选择。
public class BusinessLogic {
private BaseClassOfBeanAandB bean;
public void methodCalledByUserAorB() {
bean.doFoo();
}
}