我想了解以下代码是如何工作的。
@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();
}
这是工作代码。
我想了解,bean 创建是如何工作的。
下面的代码创建了一个bean。
@Bean
public StateHandlerDef handler() {
return () -> StateOne.class;
}
StateOne 类有一个构造函数。但是,这会在不传递构造函数参数的情况下创建 bean。此外,返回类型是一个函数接口,它没有由实际状态类实现,并且不确定它是如何工作的。这是基于 Akka actor 模型。
AbstractStateActorActor extends AbstractUntypedActor
在这里,我想以编程方式设置bean名称,而不是通过注释设置。
@Bean(“测试”)
如果我尝试使用 BeanPostProcessor 以编程方式设置 bean 名称,则会抛出错误,无法使用 new 创建实例,而应该使用 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]
对此有什么帮助吗?
要理解这一点,请这样想。您尝试扩展的库(在本例中为 akka)需要知道将处理状态的类。为此,它获取类型为
StateHandlerDef
的实例(bean)。该实例是由以下代码中的 lambda 表达式创建的:
@Bean
public StateHandlerDef handler() {
return () -> StateOne.class;
}
相当于:
@Bean
public StateHandlerDef handler() {
return new StateHanderDefImpl();
}
库将使用它来获取
StateOne.class
,它将寻找一个 bean 并从依赖注入框架中获取它。该 bean 在这里定义:
@Named
@Scope("prototype")
public class StateOne extends AbstractStateActorActor<StatObject> {
@Inject
public StateOne(final Props prop, final StatRegistry statRegistry) {
super("test", transformationConfig, GenericStateObject.class, statRegistry);
}
}
DI 框架将通过在其构造函数中注入所需的依赖项来从此类创建一个 bean。
@FunctionInterface 是一种特殊类型的接口,它实际上限制用户不能包含多个 SAM(单一抽象方法)。对于下面的示例,我们有一个方法,它将提供扩展 Object 类的任何类。
@FunctionalInterface
interface ClassHandleDef {
Class<? extends Object> getHandlerClass();
}
现在我们正在创建接口 ClassHandleDef 的匿名类并提供 gethandlerClass 方法的主体。
new ClassHandleDef() {
@Override
public Class<? extends Object> getHandlerClass() {
return String.class;
}
};
现在我们正在删除不需要的额外代码。根据 lambda 表达式,删除所有额外代码,并提供参数(如果存在)以及方法的主体定义以及 lambda 运算符。
() -> String.class;
如果只有一个参数,则不需要括号。例如
a -> a*2;
我希望您了解 lambda 表达式的工作流程。感谢您花时间阅读这篇文章。
StateHandlerDef
在某种程度上表示 getter 函数
getHandlerClass()
,它是在其类定义中使用 lambda 定义定义的。附有以下声明;
@Bean
public StateHandlerDef handler() {
return () -> StateOne.class; // a supplier, no input, returns value (getter)
}
我们本质上是通过定义
StateHandlerDef
方法来实现
getHandlerClass()
接口。这就是为什么 lambda 的返回值与 getter 方法相同,
StateOne
的类型为
Class<? extends AbstractUntypedActor>
。所以在某种程度上,我们创建的 bean 如下所示;
public interface StateHandlerDef {
Class<? extends AbstractUntypedActor> getHandlerClass();
}
public class StateHandlerDefImpl implements StateHandlerDef {
// explicit way of writing lambda "() -> StateOne.class"
Class<? extends AbstractUntypedActor> getHandlerClass() {
return StateOne.class;
}
}
@Bean
public StateHandlerDef handler() {
return new StateHandlerDefImpl(); // then we use the getter thru this bean.
}
使用
@FunctionalInterface
,我们可以跳过上面给出的接口的实现,而只需将接口本身与传递的 lambda 一起使用(这是一个Supplier)。 现在你可以这样做;
@Autowire
private StateHandlerDef handler;
public .. someLogic() {
...
handler.getHandlerClass(); // will trigger the lambda, returning `StateOne.class`
...
}
只需更改 bean 的创建方法的名称即可更改 bean 的名称。
@Bean handler()
将生成名为
handler
的 bean。我试图简化,希望它可以理解,否则请检查