Spring Boot中如何从Enum构造器调用非静态Lambda方法?
问题:枚举如何引用非静态实例方法?
我尝试创建一个Enum,每个枚举值对应一个可调用的自定义方法,但编译器提示该方法必须是静态的,请问是否有办法引用非静态方法?
我的代码如下:
public class Foo { private enum MyEnum { TGD410(Foo::doAction); private MyLambda myLambda; MyEnum(MyLambda myLambda) { this.myLambda = myLambda; } public void execute(String str1, String str2) { myLambda.apply(str1, str2); } } public void doAction(String str1, String str2) { } @FunctionalInterface public interface MyLambda{ void apply(String str1, String str2); } }
我是否有其他实现方式?我认为需要传入Foo对象的引用,但不确定如何指定,因为此时的this指向Enum实例。
补充说明:我使用的是Spring Boot,Foo是一个Bean,目标方法依赖其他注入值,因此无法设为静态。我正考虑不使用Lambda,而是将方法放到可实例化的、实现通用接口的POJO中。
解决方案
方案一:修改枚举,调用时传入Foo实例
枚举是类级别的静态成员,初始化阶段无法绑定具体的Foo实例,所以可以调整execute方法,让它接收Foo实例作为参数,把实例传递给方法引用执行:
public class Foo { private enum MyEnum { TGD410(Foo::doAction); private MyLambda myLambda; MyEnum(MyLambda myLambda) { this.myLambda = myLambda; } // 新增Foo实例参数,传递给lambda执行 public void execute(Foo fooInstance, String str1, String str2) { myLambda.apply(fooInstance, str1, str2); } } public void doAction(String str1, String str2) { // 这里可以直接使用注入的依赖 } // 调整函数式接口,增加Foo实例参数 @FunctionalInterface public interface MyLambda{ void apply(Foo foo, String str1, String str2); } // 内部调用示例 public void testExecute() { MyEnum.TGD410.execute(this, "test1", "test2"); } }
方案二:将操作封装为Spring Bean,通过枚举关联(适配Spring场景)
既然Foo是Spring Bean且方法依赖注入,推荐把每个操作逻辑封装成独立的ActionHandler Bean,用枚举关联对应的处理器,从Spring容器中获取实例执行:
- 定义统一处理器接口
public interface ActionHandler { void handle(String str1, String str2); }
- 实现具体处理器Bean
@Component public class Tgd410Handler implements ActionHandler { // 直接注入依赖 @Autowired private SomeDependency someDependency; @Override public void handle(String str1, String str2) { // 编写具体业务逻辑 someDependency.process(str1); } }
- 修改枚举关联处理器Bean
public class Foo { private enum MyEnum { // 关联处理器的Bean名称(Spring默认类名首字母小写) TGD410("tgd410Handler"); private String handlerBeanName; MyEnum(String handlerBeanName) { this.handlerBeanName = handlerBeanName; } public ActionHandler getHandler(ApplicationContext context) { return context.getBean(handlerBeanName, ActionHandler.class); } } @Autowired private ApplicationContext context; // 调用示例 public void runAction(MyEnum actionType, String str1, String str2) { ActionHandler handler = actionType.getHandler(context); handler.handle(str1, str2); } }
这种方式将操作逻辑解耦,符合Spring Bean管理机制,后续新增操作只需添加新的处理器Bean和枚举值即可。
方案三:枚举存标识,实例内部分发执行
如果不想引入额外Bean,可以在枚举中定义方法标识,在Foo实例中通过分支调用对应非静态方法:
public class Foo { private enum MyEnum { TGD410; } @Autowired private SomeDependency someDependency; public void execute(MyEnum actionType, String str1, String str2) { switch (actionType) { case TGD410: doAction(str1, str2); break; // 新增操作直接添加case分支 } } public void doAction(String str1, String str2) { someDependency.doSomething(str1); } }
这种方式简单直接,适合操作类型较少的场景。
内容的提问来源于stack exchange,提问作者Peter Kronenberg
相关产品推荐
相关产品推荐

