简体   繁体   English

是否可以在Spring Framework中使用Java配置编写类似Guice的模块?

[英]Is it possible to write a Guice-like module in Spring Framework with Java configuration?

I was wondering if there was a sort of compromise that allowed you to emulate/leverage the Google Guice style EDSL way of writing modules which binds interfaces to implementations in Spring. 我想知道是否存在某种折衷方案,允许您模仿/利用Google Guice风格的EDSL编写模块的方式,这些模块将接口绑定到Spring中的实现。

For example, say I had a Google Guice Module that looked like this: 例如,假设我有一个Google Guice模块,如下所示:

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

This binds the BillingService interface to the RealBillingService implementation. 这将BillingService接口绑定到RealBillingService实现。

One way that I think I can do utilizing Spring's Java configuration class is something that looks like this 我认为我可以使用Spring的Java配置类的一种方式是这样的

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

I was wondering if there was a better way to do this or if this broke down with increasingly complex usage. 我想知道是否有更好的方法来做到这一点,或者如果这种情况随着日益复杂的使用而中断。

I really like Google Guice and how it does Dependency Injection but that's kind of all it does. 我真的很喜欢Google Guice以及它如何进行依赖注入,但这就是它的全部功能。 Spring does a lot more (yes, its dependency injection mechanism is still not 'as-nice' as Guice) but undeniably has some great projects that we would like to utilize like Spring Data, Spring Data REST, etc. which eliminate the need for writing a ton of boilerplate code. Spring做得更多(是的,它的依赖注入机制仍然不像Guice那样“很好”)但无可否认有一些我们想要利用的很棒的项目,比如Spring Data,Spring Data REST等,它们不需要写了大量的样板代码。

The way to do this is to use @Profile to include different implementations of the same interface. 这样做的方法是使用@Profile包含同一接口的不同实现。

A simple example would be DataSource . 一个简单的例子是DataSource This can however easily be extended to any other interfaces with multiple implementations. 然而,这可以容易地扩展到具有多个实现的任何其他接口。

As an example: 举个例子:

@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();
    }
}

and then for use in production: 然后用于生产:

@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");
    }

}

Then all you need to do is declare which profiles are active when you start your application context and @Inject / @Autowir e DataSource where you need it. 然后,您需要做的就是在启动应用程序上下文时声明哪些配置文件处于活动状态,并在需要的地方声明@Inject / @Autowir e DataSource

I've used both Guice and Spring a fair bit. 我已经同时使用了GuiceSpring As far as I know, the spring usage you show in the question is the only way to achieve the same as the binding in Guice with Spring. 据我所知,你在问题中显示的弹簧用法是实现与Guice with Spring中的绑定相同的唯一方法。 If you need to inject dependencies you can always include those as arguments to the @Bean method and have spring inject them for you. 如果你需要注入依赖项,你可以将它们作为@Bean方法的参数包含在内,并让spring为你注入它们。

It's definitely not as clean but it works the same way. 它绝对不是那么干净但它的工作方式相同。 One key thing to watch out for is that the default scope in spring is Singleton rather than a new instance every time (spring calls this scope prototype ) 需要注意的一件事是,spring中的默认范围是Singleton而不是每次都是一个新实例(spring调用此范围prototype

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM