自定义Spring Bean参数

7

我正在使用activator上发布的Spring Akka示例来创建Spring管理的bean actors。这是我目前使用的代码,包括演示类:

@Component
class Test extends UntypedActor {

    @Autowired
    protected ObjectMapper objectMapper;

    protected final Account account;
    protected final Order order;

    public Test(Account account, Order order) {
        this.account = account;
        this.order = order;
    }

    @Override
    public void onReceive(Object message) throws Exception {
        if (message instanceof SomeCommand) {
            // Do something using the order and the account;
        } else if (message instanceof FooCommand) {
            // More stuff
        }
    }
}

@Component
public class SpringExtension extends AbstractExtensionId<SpringExtensionImpl> implements ExtensionIdProvider {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public SpringExtensionImpl createExtension(ExtendedActorSystem system) {
        return applicationContext.getBean(SpringExtensionImpl.class);
    }

    @Override
    public ExtensionId<? extends Extension> lookup() {
        return applicationContext.getBean(SpringExtension.class);
    }

}

@Component
public class SpringExtensionImpl implements Extension {

    @Autowired
    private ApplicationContext applicationContext;

    public Props props(String actorBeanName) {
        return Props.create(SpringActorProducer.class, applicationContext, actorBeanName);
    }

}

public class SpringActorProducer implements IndirectActorProducer {

    private final ApplicationContext applicationContext;
    private final String actorBeanName;

    public SpringActorProducer(ApplicationContext applicationContext, String actorBeanName) {
        this.applicationContext = applicationContext;
        this.actorBeanName = actorBeanName;
    }

    @Override
    public Actor produce() {
        return (Actor) applicationContext.getBean(actorBeanName);
    }

    @Override
    public Class<? extends Actor> actorClass() {
        return (Class<? extends Actor>) applicationContext.getType(actorBeanName);
    }

}
现在我的问题是,如何使用自定义构造函数参数实例化演员。我考虑过使用工厂或setter方法,但我认为这不是一个选项,因为底层的Actor类不可访问。非常感谢您对此事的任何意见。如果有什么不清楚的地方,请发表评论。 附注:如果您认为我的代码中存在错误或有更好的处理方式,请告诉我!我对Spring和Akka的结合经验很少,所以任何建议都会受到赞赏。

我的第一个评论是,你的UntypedActor类应该有@Scope("prototype")注释以及@Component。这是必需的,因为每次您请求Spring扩展创建此类型的actor时,您希望它生成一个新实例。单例bean概念在这里不适用。 - nickebbitt
回答你的问题,从经验来看,混合使用创建Actor的方法是不可行的。要么所有依赖项都需要通过Spring进行注入,要么根本不使用Spring,而是使用标准的Akka方式使用构造函数注入。以您上面的示例为例,如果Account和Order是Spring bean,则可以像ObjectMapper一样注入它们。或者将ObjectMapper添加到构造函数参数中,并在创建此Actor的新实例时以这种方式进行注入,而不使用Spring。 - nickebbitt
只是补充一下,如果您的Account和Order实例是Spring bean,则应该能够将@Autowired注释添加到它们的构造函数中,以便它们也可以被注入。 - nickebbitt
它们不是Spring Beans。它们是使用ORM框架获取的。 - Martijn
如果你忽略了Akka的存在,那么该怎么创建带有自定义构造函数的bean呢? - Martijn
显示剩余2条评论
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
5
你可以将额外的参数作为可变参数 (Object...) 传递给 SpringExtensionImplSpringActorProducer。因此,您的代码应该如下所示:
@Component
public class SpringExtensionImpl implements Extension {

   @Autowired
   private ApplicationContext applicationContext;

   public Props props(String actorBeanName, Object... args) {
       return (args != null && args.length > 0) ?
            Props.create(SpringActorProducer.class,
                    applicationContext,
                    actorBeanName, args) :
            Props.create(SpringActorProducer.class,
                    applicationContext,
                    actorBeanName);
    }
}

public class SpringActorProducer implements IndirectActorProducer {

    private final ApplicationContext applicationContext;
    private final String actorBeanName;
    private final Object[] args;

    public SpringActorProducer(ApplicationContext applicationContext, String actorBeanName) {
        this.applicationContext = applicationContext;
        this.actorBeanName = actorBeanName;
        this.args = null;
    }

    public SpringActorProducer(ApplicationContext applicationContext, String actorBeanName, Object... args) {
        this.applicationContext = applicationContext;
        this.actorBeanName = actorBeanName;
        this.args = args;
    }

    @Override
    public Actor produce() {
        return args == null ? 
              (Actor) applicationContext.getBean(actorBeanName):
              (Actor) applicationContext.getBean(actorBeanName, args);
    }

    @Override
    public Class<? extends Actor> actorClass() {
        return (Class<? extends Actor>) applicationContext.getType(actorBeanName);
    }

}
您可以按照以下方式创建Test actor: SpringExtensionImpl springExtensionImpl; actorSystem.actorOf(springExtensionImpl.create(Test.class, account, order)); 这段代码涉及到IT技术,它允许您创建一个名为Test的actor。

1
请记住,在创建演员时,该行中的SpringExtensionImpl将是实际对象,而不是类名,因为该类不是静态的。 - Will Brode

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,