如何在运行时选择Spring bean实例

Eng*_*_DJ 10 java spring

基于传递给方法的参数,我需要从许多Spring bean中选择一个,这些Spring bean是同一个类的实现,但配置了不同的参数.

例如,如果用户A调用该方法,我需要调用dooFoo()bean A,但如果它是用户B,那么我需要调用相同的方法,仅在bean B上调用.

除了将所有bean都粘贴在地图中,并从传递给我的方法的参数中获取一个键之外,还有一种"更加睿智"的方法吗?

Car*_*ron 10

我们在项目中遇到了这个问题,我们通过类似Factory的类来解决它.客户端类 - 在运行时需要bean的客户端类 - 有一个工厂实例,它是通过Spring注入的:

@Component
public class ImTheClient{

    @Autowired
    private ImTheFactory factory;

    public void doSomething(
            Parameters parameters) throws Exception{        
        IWantThis theInstance = factory.getInstance(parameters);        

    }

}
Run Code Online (Sandbox Code Playgroud)

因此,IWantThis实例取决于parameters参数的运行时值.Factory实现如下:

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,工厂实例保持对类的两个可能值的引用IWantThis,IWantThisBadly以及IAlsoWantThis两者的实现IWantThis.


Jos*_*tin 2

似乎您想要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);
            }
        }
    }   
}
Run Code Online (Sandbox Code Playgroud)