Lambda 运算符 () -> 如何工作?

问题描述 投票:0回答:3

我想了解以下代码是如何工作的。

@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]

对此有什么帮助吗?

java spring akka
3个回答
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
投票

@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;
  • 如果有单行方法定义,则无需显式编写 return 语句。
  • 如果只有一个参数,则不需要括号。例如

    a -> a*2;

我希望您了解 lambda 表达式的工作流程。感谢您花时间阅读这篇文章。


1
投票
那里的函数接口

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。

我试图简化,希望它可以理解,否则请检查

this

© www.soinside.com 2019 - 2024. All rights reserved.