我想了解以下代码的工作原理。
@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演员模型的。
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]
对此有任何帮助吗?
答案 0 :(得分:2)
要理解这种想法。您尝试扩展的库(在本例中为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。
答案 1 :(得分:1)
StateHandlerDef
的功能接口以某种方式表示使用Lambda定义在其类定义中定义的吸气剂功能getHandlerClass()
。带有以下声明;
@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 handler()
将生成名称为handler
的bean。
我试图简化,希望它可以理解,否则请检查this
答案 2 :(得分:1)
@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表达式的工作流程。感谢您抽出宝贵的时间阅读这篇文章。