gpt4 book ai didi

spring - Groovy + Spring - 没有样板(构造函数)代码的 DI

转载 作者:行者123 更新时间:2023-12-02 01:06:58 33 4
gpt4 key购买 nike

我创建了基于 Groovy 而不是 Java 的 spring-boot 项目。

现在我有关注 @RestController :

@RestController
class HelloRest {

private final HelloService helloService

@GetMapping("hello")
String hello(@RequestParam("name") String name) {
helloService.createHelloMessage(name)
}
}

问题是如何注入(inject)
@Service
class HelloService {...}

以最简单的方式避免样板代码(在这种情况下是构造函数)代码?

在 Java 中我会使用: @lombok.RequiredArgsConstructor 事实上,如果我在我的 groovy 项目中使用它,它也可以工作。

另一方面,例如 @不可变 来自 的注释groovy.transform 不起作用,因为它实际上创建的不仅仅是单个构造函数。而 Spring 期望单个构造函数能够自动 @Autowired 依赖项。

据我所知,有两种解决方案:
  • 生成构造函数
  • 使用带有注释的 lombok

  • 是否有任何内置到 Groovy 的解决方案可以在这里使用?

    最佳答案

    目前没有与 @lombok.RequiredArgsConstructor 做同样事情的 Groovy 机制。 .您的情况的主要问题是,Groovy 总是为所有当前已知的功能(如 @Immutable)生成无参数默认构造函数。注解。最接近(但不准确)的方法是使用 @TupleConstructor 像:

    @RestController
    @TupleConstructor(includes = ['helloService'], includeFields = true, includeProperties = false, force = true)
    class HelloRest {

    private final HelloService helloService

    @GetMapping("hello")
    String hello(@RequestParam("name") String name) {
    return helloService.createHelloMessage(name)
    }
    }

    此 Groovy 代码将生成类似于此 Java 代码的字节码:
    @RestController
    @TupleConstructor(
    includeFields = true,
    force = true,
    includeProperties = false,
    includes = {"helloService"}
    )
    public class HelloRest implements GroovyObject {
    private final HelloService helloService;

    public HelloRest(HelloService helloService) {
    CallSite[] var2 = $getCallSiteArray();
    MetaClass var3 = this.$getStaticMetaClass();
    this.metaClass = var3;
    this.helloService = (HelloService)ScriptBytecodeAdapter.castToType(helloService, HelloService.class);
    }

    public HelloRest() {
    CallSite[] var1 = $getCallSiteArray();
    this((HelloService)null);
    }

    @GetMapping({"hello"})
    public String hello(@RequestParam("name") String name) {
    CallSite[] var2 = $getCallSiteArray();
    return (String)ShortTypeHandling.castToString(var2[0].call(this.helloService, name));
    }
    }

    这几乎是您所需要的,除了生成的这个默认构造函数。

    使用 @Immutable 时,事情变得更加复杂。注释,因为这个版本会生成 3 个构造函数:
  • public HelloRest(HelloService helloService)
  • public HelloRest()
  • public HelloRest(HashMap args)

  • 当然,在这种情况下,您必须删除 private finalHelloService 前面字段定义,因为此 AST 转换仅适用于尚未最终确定的字段。

    在这种情况下,您找到的两个选项(手动创建构造或使用 Lombok)可能是解决问题的最佳方法。

    替代解决方案

    还有一种“肮脏”的解决方案可以让您编写更少的代码,但通过反射促进注入(inject)。考虑以下代码:
    @RestController
    class HelloRest {

    @Autowired
    private final HelloService helloService

    @GetMapping("hello")
    String hello(@RequestParam("name") String name) {
    return helloService.createHelloMessage(name)
    }
    }

    它将生成类似于以下 Java 代码的字节码:
    @RestController
    public class HelloRest implements GroovyObject {
    @Autowired
    private final HelloService helloService;

    public HelloRest() {
    CallSite[] var1 = $getCallSiteArray();
    MetaClass var2 = this.$getStaticMetaClass();
    this.metaClass = var2;
    }

    @GetMapping({"hello"})
    public String hello(@RequestParam("name") String name) {
    CallSite[] var2 = $getCallSiteArray();
    return (String)ShortTypeHandling.castToString(var2[0].call(this.helloService, name));
    }
    }

    即使只有一个默认构造函数甚至没有触及我们的 helloService字段,Spring bean 将通过反射注入(inject)。我分享这个选项只是为了展示所有的替代方案,尽管你最初使用构造函数注入(inject)的本能是在实践中使用依赖注入(inject)的最佳方式。

    关于spring - Groovy + Spring - 没有样板(构造函数)代码的 DI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47113439/

    33 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com