动态使用Spring注入服务实现

huangapple go评论69阅读模式
英文:

Dynamically inject service implementation with Spring

问题

以下是您要翻译的内容:

"I've already gone through some tips on how to do this, like this one: stack overflow; but my problem is that my own implementation needs other things to be injected in it. Here's the example:

public interface MyService {}

public class ServiceImplA implements MyService {

     @Autowired
     private final SomeStuffA a_stuff;

}

public class ServiceImplB implements MyService {

     @Autowired
     private final SomeStuffB b_stuff;

}

@Configuration
public class SpringConfig {

    @Bean
    @Scope("singleton")
    public MyService getService() {
         boolean useA = // read config file and decide impl
         return useA ? new ServiceImplA() : new ServiceImplB();
         // I can't instantiate this, so i need them to be injected as well
    }

}

I'm familiar with Google Guice, where I would do something like this:

bind(MyService.class).to(useA ? ServiceImplA.class :  ServiceImplB.class);

So, I need a way to do this using Spring

英文:

I've already gone through some tips on how to do this, like this one: stack overflow; but my problem is that my own implementation needs other things to be injected in it. Here's the example:

public interface MyService {}

public class ServiceImplA implements MyService {

     @Autowired
     private final SomeStuffA a_stuff;

}

public class ServiceImplB implements MyService {

     @Autowired
     private final SomeStuffB b_stuff;

}

@Configuration
public class SpringConfig {

    @Bean
    @Scope("singleton")
    public MyService getService() {
         boolean useA = // read config file and decide impl
         return useA ? new ServiceImplA() : new ServiceImplB();
         // I can't instantiate this, so i need them to be injected as well
    }

}

I'm familiar with Google Guice, where I would do something like this:

bind(MyServicle.class).to(useA ? ServiceImplA.class :  ServiceImplB.class);

So, I need a way to do this using Spring

答案1

得分: 2

我认为你的问题在于你的基类 MyService 没有标记任何配置文件。

当你定义配置文件时,具有这种规范的 bean 会覆盖实现相同接口但没有配置文件定义的 bean。然而,这种方式是行不通的。

在使用活动配置文件 X 时,Spring 会启动所有没有针对任何配置文件的 bean,以及针对当前配置文件的 bean。在你的情况下,你可以进行明智的选择。

我认为,如果你想使用配置文件,你至少应该定义两个:AB(名称仅为示例)。

现在将 ServiceImplA 标记为 A,将 ServiceImplB 标记为 B

@Service
@Profile("A") 
public class ServiceImplA implements MyService { ... }
// 一些开发实现

@Service
@Profile("B") 
public class ServiceImplB implements MyService { ... }

关于配置文件的更多信息,你可以在这里找到。

英文:

I think your problem is that your base class MyService is not marked for any profile.

When you define profile the beans that have such specification will override beans that implement the same interface and do not have profile definition. This does not work this way.

When working with active profile X spring starts all beans that are not targeted for any profile and beans targeted for current profile. In your case you can choose wisely.

I think that if you want to use profiles you should define at least 2: A and B (the names are taken just for example.)

Now mark ServiceImplA as A and ServiceImplB as B:

@Service
@Profile("A") 
public ServiceImplA interface MyService { ... }
and some development implementation

@Service
@Profile("B") 
public ServiceImplB interface MyService { ... }

More about profiling you will get here

huangapple
  • 本文由 发表于 2020年9月3日 01:35:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63710831.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定