10

我们决定为我们未来的模块化工作使用带有 JSR-330 注释的依赖注入,并且对基于 Guice 2 SVN 的第一个可交付成果感到非常满意。

现在我们需要通过单元测试确保并记录我们需要的构造,当以编程方式配置时也可以在 Spring 中工作(我们希望与 Guice 相同的重构支持,因此没有 XML 文件)。我有问题,@Provider@Inject @Named("foo") String我已经做了简单@Inject的工作:

ApplicationContext ctx = new AnnotationConfigApplicationContext(LIBL_Object.class, 
                                                                CORE_Provider.class);
this.object = ctx.getBean(LIBL_Object.class);

其中 LIBL_Object 是要注入的基类但 CORE_Provider 没有像我希望的那样在 Spring 中注册。

CORE_Provider 的实现是

package qa.jsr330.core;

import javax.inject.Provider;

public class CORE_Provider implements Provider<ProvidedInterface> {
    @Override
    public ProvidedInterface get() {
        return new CORE_Provided();
    }
}

我想把它注入

package qa.jsr330.core;

import javax.inject.Inject;

public class LIBL_Object {

    private ProvidedInterface provided;

    public ProvidedInterface getProvided() {
        return provided;
    }

    @Inject
    public void setProvided(ProvidedInterface provided) {
        this.provided = provided;
    }
// Other stuff omitted.
}

我们还发现我们可以使用@Named 标签非常清楚地传递配置值。此代码如下所示:

String hostname;
@Inject
public void setHostname(@Named("as400.hostname") String hostname) {
    this.hostname = hostname;
}

然后我们可以使用 Guice 注册这个字符串

bindConstant().annotatedWith(Names.named("as400.hostname")).to(value);

所以这两个问题是:

  • 如何@Provider以编程方式向 Spring 3 注册课程?
  • 如何使用 Spring 3 注册一个字符串常量,以便 @Named 正确选择它?
4

1 回答 1

6

简短的回答是:没有像 Spring 的编程配置这样的东西。

尽管 Spring 和 Guice 都支持 JSR-330 API 并且 Spring 现在可以在没有 XML 的情况下进行配置,但它们的意识形态仍然非常不同。Spring 依赖于静态配置,可以是 XML 文件的形式,也可以是带注释的 Java 类。因此,直接尝试将 Guice 风格的配置适应 Spring 可能会产生困难。

关于问题Provider- Spring 不支持与 Guicejavax.inject.Provider中的绑定相同的方式(顺便说一下, JSR-330 文档中没有指定toProvider()这种用法)。Provider因此可能需要一些 Spring 特定的注释,例如

@Configuration
public class CORE_Provider implements Provider<ProvidedInterface> {
      @Override @Bean
      public ProvidedInterface get() {
          return new CORE_Provided();
      }
} 

由于 Spring 配置的静态特性,来自外部的绑定值可能很困难。例如,在您的情况下,可以这样做:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(IBL_Object.class);
ctx.register(CORE_Provider.class);
ctx.registerBeanDefinition("as400.hostname",
    BeanDefinitionBuilder.rootBeanDefinition(String.class)
        .addConstructorArgValue(value).getBeanDefinition());
ctx.refresh();
于 2011-01-03T14:32:33.133 回答