我有一个服务(我们称它为 TaskExecutorService
),它需要一个依赖项 TaskService
。
我习惯于通过构造函数注入(inject)依赖,所以我使用了以下代码:
@Service
class TaskExecutorService {
private final TaskService taskService;
public TaskExecutorService(TaskService taskService) {
this.taskService = taskService;
}
void function1() {...}
void function2() {...}
}
TaskService
有一个依赖项TaskRetrieverService
,它是一个接口(interface),由多个用@Service 注释的“检索器”实现。
@Service
class TaskService {
private final TaskRetrieverService taskRetrieverService;
public TaskService(TaskRetrieverService taskRetrieverService) {
this.taskRetrieverService = taskRetrieverService;
}
}
在 TaskExecutorService
中注入(inject) TaskService
并选择使用哪个检索器的最佳方法是什么?
此外,我的实际用例是根据 TaskExecutorService
中的函数(function1
或 function2
),我希望能够使用“猎犬”或其他。
我认为我可以使用其构造函数直接在方法中实例化 TaskService
,但我希望有一个最好的方法来执行此操作。
最佳答案
我同意这是某种反模式,因为您正在连接 @Bean
,但我需要这样做几次并且没有义务对接口(interface)实现进行硬编码。
答案是,您可以在使用 @Bean(name = "customName")
在 Spring Config 中声明 bean 时为其命名。这样,您就可以选择要使用的接口(interface)实现。
对于以下示例(根据您的情况),我有一个名为 Dependency.java
的接口(interface)依赖项。对于这个例子,让我们保持简单,它只有一个方法 print()
,它会根据我们在运行时使用的实现打印一些东西。
public interface Dependency {
void print();
}
对于这种依赖,我有两种可能的实现方式。它们是 Child1
和 Child2
。
这是Child1.java
public class Child1 implements Dependency {
@Override
public void print() {
System.out.println("I'm Child1!");
}
}
这是Child2.java
public class Child2 implements Dependency {
@Override
public void print() {
System.out.println("I'm Child2!");
}
}
如您所见,它们仅从我们的 Dependency.java
中实现,不做任何其他事情。他们实现该方法,该方法打印一条语句以区分正在运行时实现的方法。
然后我有一个名为 SpringConfig.java
@Configuration
@ComponentScan("you.packages.go.here.for.discovery.**.*")
public class SpringConfig {
@Bean(name = "myBean1")
public Dependency dependency() {
return new Child1();
}
@Bean(name = "myBean2")
public Dependency dependency2() {
return new Child2();
}
}
在这里,我声明了 2 个 bean,每个 bean 都有一个唯一名称。对于此示例,第一个实现 (Child1
) 将称为 myBean1
,第二个实现 (Child2
) 将称为 myBean2
.
然后我有了 @Service
类,它将使用这两个 @Beans
之一。 我使用 Spring 在此处连接 Context
,而不是使用 new Child1()
进行硬连接。这样我就可以根据逻辑选择我想选择的。
@Service
public class MyService implements ApplicationContextAware {
private ApplicationContext context;
public void useDependency() {
Dependency dependency = (Dependency) context.getBean("myBean2");
dependency.print();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
上下文由 implements ApplicationContextAware
实现。这将添加保存 ApplicationContext
的 setApplicationContext()
方法。有了这个上下文后,您只需选择要在上一行中使用哪个接口(interface)实现
Dependency dependency = (Dependency) context.getBean("myBean2");
如果您将 myBean2
更改为 myBean1
(或您在 SpringConfig
的参数 @Bean 中设置的任何其他名称(name = "something")
你会将运行时实现更改为那个 @Bean
)。
我实现了 @Bean
myBean2
,所以正如预期的那样,这将打印
"I'm Child2!"
关于java - 有没有办法注入(inject)一个依赖项,该依赖项将根据注入(inject)的位置(使用 Spring 引导)使用特定的 bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63941645/