是否可以使用 Java 配置在 Spring 框架中编写类似 Guice 的模块?
Is it possible to write a Guice-like module in Spring Framework with Java configuration?
我想知道是否有某种妥协允许您 emulate/leverage Google Guice 风格的 EDSL 编写模块的方式,将接口绑定到 Spring 中的实现。
例如,假设我有一个 Google Guice 模块,如下所示:
public class BillingModule extends AbstractModule {
protected void configure() {
bind(BillingService.class).to(RealBillingService.class);
}
}
这将 BillingService
接口绑定到 RealBillingService
实现。
我认为我可以利用 Spring 的 Java 配置 class 的一种方式看起来像这样
@Configuration
public class BillingConfiguration {
@Bean
public BillingService getRealBillingService() {
return new RealBillingService();
}
}
我想知道是否有更好的方法来做到这一点,或者这种方法是否会随着使用越来越复杂而崩溃。
我真的很喜欢 Google Guice 以及它如何进行依赖注入,但仅此而已。 Spring 做了更多(是的,它的依赖注入机制仍然不像 Guice 'as-nice')但不可否认有一些我们想利用的伟大项目,如 Spring 数据,Spring Data REST 等消除了编写大量样板代码的需要。
我用过 Guice
和 Spring
。据我所知,您在问题中显示的 spring 用法是实现与 Guice 中使用 Spring 绑定相同的唯一方法。如果您需要注入依赖项,您始终可以将它们作为参数包含在 @Bean
方法中,并让 spring 为您注入它们。
它绝对不是那么干净,但它的工作方式是一样的。需要注意的一件关键事情是 spring 中的 default 范围是 Singleton
而不是每次都创建一个新实例(spring 调用此范围prototype
)
实现这一点的方法是使用@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
/@Autowir
e DataSource
。
我想知道是否有某种妥协允许您 emulate/leverage Google Guice 风格的 EDSL 编写模块的方式,将接口绑定到 Spring 中的实现。
例如,假设我有一个 Google Guice 模块,如下所示:
public class BillingModule extends AbstractModule {
protected void configure() {
bind(BillingService.class).to(RealBillingService.class);
}
}
这将 BillingService
接口绑定到 RealBillingService
实现。
我认为我可以利用 Spring 的 Java 配置 class 的一种方式看起来像这样
@Configuration
public class BillingConfiguration {
@Bean
public BillingService getRealBillingService() {
return new RealBillingService();
}
}
我想知道是否有更好的方法来做到这一点,或者这种方法是否会随着使用越来越复杂而崩溃。
我真的很喜欢 Google Guice 以及它如何进行依赖注入,但仅此而已。 Spring 做了更多(是的,它的依赖注入机制仍然不像 Guice 'as-nice')但不可否认有一些我们想利用的伟大项目,如 Spring 数据,Spring Data REST 等消除了编写大量样板代码的需要。
我用过 Guice
和 Spring
。据我所知,您在问题中显示的 spring 用法是实现与 Guice 中使用 Spring 绑定相同的唯一方法。如果您需要注入依赖项,您始终可以将它们作为参数包含在 @Bean
方法中,并让 spring 为您注入它们。
它绝对不是那么干净,但它的工作方式是一样的。需要注意的一件关键事情是 spring 中的 default 范围是 Singleton
而不是每次都创建一个新实例(spring 调用此范围prototype
)
实现这一点的方法是使用@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
/@Autowir
e DataSource
。