【问题标题】:Is it possible to write a Guice-like module in Spring Framework with Java configuration?是否可以使用 Java 配置在 Spring Framework 中编写类似 Guice 的模块?
【发布时间】:2015-12-03 13:41:40
【问题描述】:

我想知道是否有某种折衷方案允许您模拟/利用 Google Guice 风格的 EDSL 编写模块的方式,该方式将接口绑定到 Spring 中的实现。

例如,假设我有一个如下所示的 Google Guice 模块:

public class BillingModule extends AbstractModule {
    protected void configure() {
        bind(BillingService.class).to(RealBillingService.class);
    }
}

这将BillingService 接口绑定到RealBillingService 实现。

我认为我可以使用 Spring 的 Java 配置类的一种方法是这样的

@Configuration
public class BillingConfiguration {
  @Bean
  public BillingService getRealBillingService() {
    return new RealBillingService();
  }
}

我想知道是否有更好的方法来做到这一点,或者这是否会随着越来越复杂的使用而崩溃。

我真的很喜欢 Google Guice 以及它如何进行依赖注入,但这就是它所做的一切。 Spring 做得更多(是的,它的依赖注入机制仍然没有 Guice 那样“好”),但不可否认的是,我们希望使用一些很棒的项目,例如 Spring Data、Spring Data REST 等,从而消除了对编写大量样板代码。

【问题讨论】:

标签: java spring dependency-injection guice


【解决方案1】:

这样做的方法是使用@Profile 来包含同一接口的不同实现。

一个简单的例子是DataSource。然而,这可以很容易地扩展到具有多种实现的任何其他接口。

举个例子:

@Configuration
public class LocalDataConfig {
@Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }
}

然后用于生产:

@Configuration
@Profile("production")
public class JndiDataConfig {

    @Bean
    public DataSource dataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }

}

然后您需要做的就是在启动应用程序上下文时声明哪些配置文件处于活动状态,并在您需要的位置声明 @Inject/@Autowire DataSource

【讨论】:

  • 不幸的是,这个答案没有解决原始问题的两个重要元素:(1)如何以编程方式在 Spring 中生成配置(即,通过调用 Guice 中的 binder 方法),以及(2)如何将对象创建牢牢地交给 DI 框架(返回 new RealBillingService()@Bean 方法仍然与 Guice 的 bind(BillingService.class).to(RealBillingService.class) 不同,后者不涉及创建任何对象)
【解决方案2】:

GuiceSpring 我都用过不少。据我所知,您在问题中显示的 spring 用法是实现与 Guice 中的 Spring 绑定相同的唯一方法。如果您需要注入依赖项,您始终可以将它们作为参数包含在 @Bean 方法中,并让 spring 为您注入它们。

它绝对不是那么干净,但它的工作方式相同。需要注意的一个关键点是 spring 中的 default 范围是 Singleton 而不是每次都是一个新实例(spring 调用这个范围 prototype

【讨论】:

    猜你喜欢
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 2014-11-17
    • 2013-06-08
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 2017-02-25
    相关资源
    最近更新 更多