【发布时间】:2014-08-13 16:02:10
【问题描述】:
我想将接口的代理实现注入到组件中,然后让 spring 根据运行时属性(以及实现类的注释值)选择正确的实现。所以我的组件不必关心选择正确的组件。
它有点像一个范围。但我认为范围仅用于处理同一实现类的不同实例。我错了吗?
我希望它可以针对任意接口运行,而无需为每个新服务创建服务定位器或其他构造。
这是一个例子。
假设我有一个定义服务的接口
package test;
public interface IService {
void doSomething();
}
还有两个实现:
package test;
import javax.inject.Named;
@Named
@MyAnnotation("service1")
public class Service1 implements IService {
@Override
public void doSomething() {
System.out.println("this");
}
}
...
package test;
import javax.inject.Named;
@Named
@MyAnnotation("service2")
public class Service2 implements IService {
@Override
public void doSomething() {
System.out.println("that");
}
}
现在我想将 IService 注入另一个组件,并让 spring 根据一些可查询的运行时属性和 MyAnnotation 的值选择正确的实现。
有没有办法在春季以一般方式做到这一点?
编辑:
我有一个具有一定价值的上下文。在这种情况下,它是一个本地线程。
package test;
public class MyValueHolder {
private static final ThreadLocal<String> value = new ThreadLocal<>();
public static void set(String newValue) {
value.set(newValue);
}
public static String get() {
return value.get();
}
public static void reset() {
value.remove();
}
}
我有一个使用IService的组件
package test;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class MyComponent {
@Inject
private IService service;
public void myImportantWorkflow(){
MyValueHolder.set("service1");
service.doSomething();
MyValueHolder.set("service2");
service.doSomething();
}
}
注入的服务应该只是一个代理。根据MyValueHolder 中设置的值,对doSomething 的调用应该委托给service1 或service2。所以在这个例子中,它应该在第一次调用中委托给 service1 上的 doSomething,在第二次调用中委托给 service2。
我可以编写这样一个实现IService 接口的委托器并将其用于这项服务。但随后我必须对其他所有服务重复此操作。我希望 spring 几乎可以自己用代理做这样的事情。当然,我必须提供一些方法来根据本地线程中的值查找bean并将其注册到spring。但我不知道在不修改弹簧框架的情况下这是否可能。如果有可能如何做到这一点。
【问题讨论】:
-
这完全取决于您所说的“让 spring 根据一些可查询的运行时属性和 MyAnnotation 的值选择正确的实现”的意思。您可能应该编写一个单元测试来充实您期望的行为。
-
'让 spring 选择正确的实现'意味着 spring 使用接口类型和注释值进行某种查找以获得正确的实现,注入的代理然后调用这个查找的实现。
-
Spring 已经检查了类型并使用@Qualifier 注解来选择要注入的bean。
-
是的,但是
@Qualifier按名称注入实现。但关键是我有两个实现,只有一个应该用于调用。应该通过检查运行时值(实际上是线程本地值)来确定哪一个。所以我在IService上调用doSomeThing()方法,现在应该检查本地线程的值。如果它包含“service1”,则调用被委托给Service1,如果它包含“service2”,它被委托给Service2。这种查找应该对使用IService的类透明地发生 -
@Finn 你能详细说明一下选择是如何发生的吗?多一点信息会有所帮助