I would like to understand, how the below code works.
@Bean
public StateHandlerDef handler() {
return () -> StateOne.class;
}
@Named
@Scope("prototype")
public class StateOne extends AbstractStateActorActor<StatObject> {
@Inject
public StateOne(final Props prop, final StatRegistry statRegistry) {
super("test", transformationConfig, GenericStateObject.class, statRegistry);
}
}
@FunctionalInterface
public interface StateHandlerDef {
Class<? extends AbstractUntypedActor> getHandlerClass();
}
This is the working code.
I would like to understand, How the bean creation work here.
Below code creates a bean.
@Bean
public StateHandlerDef handler() {
return () -> StateOne.class;
}
StateOne class has a constructor. But, this creates the bean without passing the constructor arguments. Also, the return type is a function interface which is not implemented by the actual state class and not sure how does it work. This is based an Akka actor model.
AbstractStateActorActor extends AbstractUntypedActor
Here, I would like to set the bean name programmatically instead of setting thru the annotation.
@Bean("test")
If I try BeanPostProcessor for programmatically setting the bean name, it throws error that instance cannot be created using new and should be created with actorof.
Caused by: akka.actor.ActorInitializationException: You cannot create an instance of [com.test.Test] explicitly using the constructor (new). You have to use one of the 'actorOf' factory methods to create a new actor. See the documentation.
at akka.actor.ActorInitializationException$.apply(Actor.scala:181) ~[akka-actor_2.11-2.4.19.jar:na]
Any help on this?
To understand this think of it this way. The library that you are trying to extend (in this case akka) needs to know the class that is going to handle a state. To do that it gets an instance (bean) of type StateHandlerDef
. This instance is created by the lambda expression in this code:
@Bean
public StateHandlerDef handler() {
return () -> StateOne.class;
}
which is equivalent to something like:
@Bean
public StateHandlerDef handler() {
return new StateHanderDefImpl();
}
The library will use this to get StateOne.class
, for which it will look for a bean and will get it from the dependency injection framework. That bean is defined here:
@Named
@Scope("prototype")
public class StateOne extends AbstractStateActorActor<StatObject> {
@Inject
public StateOne(final Props prop, final StatRegistry statRegistry) {
super("test", transformationConfig, GenericStateObject.class, statRegistry);
}
}
The DI framework will create a bean from this class by injecting the dependencies it needs in its constructor.