我跟踪数据库中consumerId
的服务提供商列表。
我有SchedulerActor
为TaskActor
启用的每个服务提供商创建consumerId
。
我想为列表中的每个服务提供商注入ServiceProvider
到TaskActor
的实现。 ServiceProvider
可以有不同的实现。
interface ServiceProvider {
void processRequest(Request request);
}
class SchedulerActor {
@Override
public void onReceive(Object consumerId) throws Exception {
List<String> serviceProvidersList = getFromDatabase((String) consumerId);
for (String serviceProviderStr : serviceProvidersList) {
//serviceProviderStr could be "ServiceProvider1" or "ServiceProvider2"
ServiceProvider serviceProvider = getServiceProviderFromStr(serviceProviderStr);
ActorRef r = getContext().actorOf(Props.create(TaskActor.class, serviceProvider));
getContext().watch(r);
routees.add(new ActorRefRoutee(r));
}
router = new Router(new BroadcastRoutingLogic(), routees);
router.route(message, getSelf());
}
}
class TaskActor {
private final ServiceProvider serviceProvider;
public TaskActor(ServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}
@Override
public void onReceive(Object message) {
if (message instanceof Request) {
serviceProvider.processRequest((Request)message);
}
}
}
getServiceProviderFromStr(String)
内部有什么来实现这个目标?switch
或if else
语句来返回所需的实现。 答案 0 :(得分:1)
使用Guice AssistedInject,即FactoryModuleBuilder向TaskActor构造函数添加服务名称的String参数,并使用此参数注入带有@Named注释的ServiceProvider:
在模块中定义工厂界面:
public interface TaskActorFactory{
TaskActor create(String serviceName);
}
在模块 configure 方法中安装工厂并注册服务绑定:
protected void configure() {
bind(ServiceProvider.class).annotatedWith(Names.named("serviceA")).to(ServiceA.class);
bind(ServiceProvider.class).annotatedWith(Names.named("serviceB")).to(ServiceB.class);
bind(ServiceProvider.class).annotatedWith(Names.named("serviceC")).to(ServiceC.class);
install(new FactoryModuleBuilder()
.implement(TaskActor.class, TaskActor.class)
.build(TaskActorFactory.class));
}
实施TaskActor:
@Inject
class TaskActor extends UntypedActor {
public static Props props(String serviceName) {
return Props.create(TaskActor.class, ()->new TaskActor(serviceName));
}
private final ServiceProvider serviceProvider;
public TaskActor(Injector injector, @Assisted String serviceName) {
serviceProvider = injector.getInstance(Key.get(ServiceProvider.class, Names.named(serviceName)));
}
...
}
从SchedulerActor创建TaskActor
@Override
public void onReceive(Object consumerId) throws Exception {
List<String> serviceProvidersList = getFromDatabase((String) consumerId);
for (String serviceProviderStr : serviceProvidersList) {
ActorRef r = getContext().actorOf(TaskActor.props(serviceProviderStr));
getContext().watch(r);
routees.add(new ActorRefRoutee(r));
}
...
}
}
答案 1 :(得分:1)
使用相同命名绑定而不是建议@Assisted
的另一种方法@Inject
public Injector injector;
...
ServiceProvider s = injector.getInstance(Key.get(Parent.class, Names.named(serviceName)));
其中绑定在configure()中的类:
bind(ServiceProvider.class).annotatedWith(Names.named("Name1")).to(Child1.class);
bind(ServiceProvider.class).annotatedWith(Names.named("Name2")).to(Child2.class);
答案 2 :(得分:0)
如果您不想使用pydev_file_utils.pyc
switch
,我认为您必须使用反射来执行此操作,其中if else
是类名。
serviceProviderStr
请记住,您可以通过调用 private ServiceProvider getServiceProviderFromStr(String serviceProviderClassName){
try {
Class<?> clazz = Class.forName(serviceProviderClassName);
if(!ServiceProvider.class.isAssignableFrom(clazz)){
throw new IllegalArgumentException("Argument is not a ServiceProvider class.");
}
Class<? extends ServiceProvider> serviceProviderClass = (Class<? extends ServiceProvider>) clazz;
return serviceProviderClass.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
来获取课程名称。