当前位置: 首页 > 知识库问答 >
问题:

如何用科特林做JEE EJB依赖注入

胡玉书
2023-03-14

我已经将正式用Java编写的JEE应用程序中的REST资源转换为Kotlin。该应用程序在Wildfly应用程序服务器中运行,使用Weld作为依赖项注入框架。

这是我想出的最终实现:

@Path("/myResource")
open class MyResource {

  @Context
  private lateinit var context: SecurityContext

  open protected setSecurityContext(securityContext: SecurityContext) {
    this.context = securityContext
  }

  @POST
  @Path("/change")
  @Transactional
  @Consumes(MediaType.APPLICATION_JSON)
  open internal fun change(data: MyChangeData, @Context uriInfo: UriInfo): Response {
    // ...
  }
}

setter用于测试目的。对于Mockito或其他可以设置私有字段的mocking框架,这不是必需的。

我在这个实现上遇到了一些问题:

    < li >我必须将类和所有方法更改为< code>open,以允许CDI容器为此bean创建代理。就我对这个主题的理解,没有其他方法可以让Weld在不允许子类化的情况下完成它的工作? < li >通常,Kotlin使用私有字段支持的给定修饰符(public/private/protected)为属性生成setters和getters。但是当使用< code>lateinit时,生成的字段具有与getters和setters相同的可见性。我不明白这种特殊行为的背景。使用< code>public属性会导致Weld报告不允许公共字段的错误。我如何声明该字段应该是私有的,但getter和setter是受保护的(以在测试中初始化资源)? < li >上面的代码中注释了什么?字段还是生成的方法?如果是字段:我如何只注释setter? < li >因为除了私有方法之外的所有方法都必须< code>open,所以除了私有方法之外的所有属性都被Weld容器拒绝:Kotlin创建具有相同可见性的Getters和Setters,并且容器尝试代理bean的所有方法。这不起作用,因为生成的getters和setters不是< code>open。对于私有属性,根本没有问题,因为html" target="_blank">容器不代理私有方法。据我所知,不可能将getter/setter声明为< code>open,因此不可能使用受保护的属性

编辑:添加了Ploblem 4,并将实现更改为带有setter的private。

共有2个答案

田翰林
2023-03-14

我能找到的最好的解决方案是将该属性声明为开放保护

@Context
open protected lateinit var context: SecurityContext

这样容器就可以覆盖它,来自java或groovy的测试将看到setter受到包保护。

如果您只想注释setter(我更喜欢但更冗长),您可以使用:

open protected lateinit var context: SecurityContext @Context set

或更好更短:

@set:Context
open protected lateinit var context: SecurityContext

不幸的是,这不适用于Kotlin测试,因为< code>protected变量只能被Kotlin中的子类看到。这里你必须写一个单独的访问器:

@Context
open protected lateinit var context: SecurityContext

open internal fun setTheSecurityContext(context: SecurityContext) ...

或者,您可以使用辅助构造函数:

open class MyResource() {

constructor(context: SecurityContext): this() {
  this.context = context
}

请注意,主空构造函数必须仍然存在。

以下是我问题的单独答案:

  1. 如果依赖注入框架使用代理open对于类和每个方法和属性(但私有)是必要的。
  2. 不。使用lateinit,属性与getter和setter具有相同的可见性。如果您想这样做,您必须将属性声明为可空。但是您必须使用!!在每个访问上都很尴尬。
  3. 字段。如上所述,您可以编写@Context set@set: Context来注释setter。
  4. 如1所述,除了私有属性之外,所有属性都必须声明为开放。

编辑:注意私有属性也会导致问题(用Wildfly测试)。我的建议是根本不使用私有,而是受保护。

编辑2:请注意,这些变通方法仅在EJB(如REST-Resources)上是必要的。对于简单的CDI Bean,除非它们由方面或类似方面代理,否则这不是问题。然后这篇文章也适用。

饶铭
2023-03-14
    < li >是 < li >我也不知道背景,但是您可以通过将代码改为smth来解决这个问题,就像

打开类A{@Context-private-lateinit-var_backing:SecurityContext-open-protected-var-field:SecurityContext-get()=_backding-set(value){_backning=value}

此外,您可以使用构造函数注入

 类似资料:
  • 如何在使用Kotlin的Spring Boot中正确初始化ConfigurationProperties? 目前我喜欢下面的例子: 但是它看起来很丑陋,实际上不是一个iable,foo是常量ue,应该在启动期间初始化,将来不会改变。

  • 我想在Quarkus中注入bean一个静态编程语言字段。示例文件看起来像 构造函数参数注入工作正常,但字段仍处于未初始化状态。 控制台输出: 有可能在科特林的Quarkus中使用CDI场注入吗?如果是,需要为注射设置什么才能工作? 我是从uberjar运行应用程序,而不是从本地图像运行。 jar包含生成的类org.example.InjectDemo_Bean包含一个方法的分解版本,该方法不显示任

  • 如何注入抽象类我有一个抽象类 我尝试使用< code>@Module和< code>@Binds注释来初始化该类的对象。但这并不能创建并抛出一个错误。 但这给出了错误。我犯了什么错误?请您告诉我如何为抽象类创建。我们如何注入抽象类?从文档中,它说。有时,不能注入构造函数。发生这种情况可能有多种原因。例如,不能构造函数注入接口。也不能构造函数注入不属于的类型,例如外部库中的类。在这些情况下,您可以使

  • 本文向大家介绍webapi中如何使用依赖注入,包括了webapi中如何使用依赖注入的使用技巧和注意事项,需要的朋友参考一下 本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式Ninject和Unity;由于快过年这段时间打算了解下vue.js,所以后面对webapi的分享文章可能会慢点更新,希望支持

  • 问题内容: 我正在学习具有C ++和Java背景的Kotlin。我期待下面的打印,不。我知道这对应到。默认实现不比较每个成员,即和吗?如果是这样,它会不会看到字符串值相等(因为再次映射到字符串值)?显然,我在Kotlin中还没有涉及平等与身份相关的问题。 问题答案: 您描述的默认实现仅适用于数据类。不适用于从中继承实现的常规类,只需使对象与自身相等即可。

  • 这是正确的吗? 我可以找到一个相关的问题,但它是有参数的,我不能在没有params的情况下转换它。