10

根据传递给方法的参数,我需要从许多 Spring bean 中选择一个,它们是同一个类的实现,但配置了不同的参数。

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

除了将所有bean粘贴在地图中并从传递给我的方法的参数中派生密钥之外,是否还有一种“Springier”方式来执行此操作?

4

4 回答 4

14

我们在项目中遇到了这个问题,我们通过类似工厂的类来解决它。客户端类——在运行时需要 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和.IAlsoWantThisIWantThis

于 2013-07-17T15:22:09.500 回答
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);
            }
        }
    }   
}
于 2013-07-18T00:25:58.063 回答
2

把它们贴在地图上听起来不错。如果它是 Spring 管理的映射(使用util:map或在 Java 配置中),那比在其他地方创建它要好,因为 Spring 拥有所有对象引用并可以正确管理它们的生命周期。

于 2013-07-17T15:05:17.997 回答
-1

如果你说的豆子(A,B)完全SessionScope没有问题,它们将被正确选择。

public class BusinessLogic {

  private BaseClassOfBeanAandB bean;

  public void methodCalledByUserAorB() {
    bean.doFoo();
  }

}
于 2013-07-17T14:10:17.890 回答