Java 如何在micronaut的线程中注入服务(或组件)?

Java 如何在micronaut的线程中注入服务(或组件)?,java,multithreading,groovy,micronaut,Java,Multithreading,Groovy,Micronaut,环境: JDK:11.0.7 操作系统:Windows 10 Micronaut:2.1.2 如何使用profile cli app在micronaut中的线程中注入服务(或组件) 下面的链接是我的代码 关键部分: @Prototype class TestWorker implements Callable { private String threadName = Thread.currentThread().name @Inject TestService test

环境:

  • JDK:11.0.7
  • 操作系统:Windows 10
  • Micronaut:2.1.2
如何使用profile cli app在micronaut中的线程中注入服务(或组件)

下面的链接是我的代码

关键部分:

@Prototype
class TestWorker implements Callable  {
    private String threadName = Thread.currentThread().name
    @Inject TestService testService

    @Override
    Object call() throws Exception {
        for(int x = 0;x < 20; x++) {
            println("${threadName}: x:${x}, ${testService.getGreeting(threadName)}")
            sleep(1000)
        }
    }
}
@原型
类TestWorker实现了可调用{
私有字符串threadName=Thread.currentThread().name
@注入TestService TestService
@凌驾
对象调用()引发异常{
对于(int x=0;x<20;x++){
println(${threadName}:x:${x},${testService.getGreeting(threadName)}”)
睡眠(1000)
}
}
}
它抛出NullPointerException,如下所示

09:08:31.254[主]信息i.m.context.env.DefaultEnvironment- 已建立的活动环境:[cli]managerId:1 workerCount:1 java.lang.NullPointerException:无法在上调用方法getGreeting() 空对象位于 org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:91) 在 org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:44) 在 org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) 在 org.codehaus.groovy.runtime.callsite.NullCallSite.call(NullCallSite.java:34) 在 org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) 在 org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) 在 org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139) 在test.multi-thread.app.TestWorker.call(TestWorker.groovy:29)处 java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)位于 java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) 在java.base/java.lang.Thread.run(Thread.java:834)处停止


在我的书中,使用
@Inject
是一种代码味道,这里我们来看看原因。您的员工需要
TestService
才能工作(没有办法解决-如果没有,您将获得NPE)

接下来,您将手动创建worker,这样它就不会参与依赖项注入。由于您只使用“deklarative”
@Inject
,因此没有任何问题,强制的服务最终会出现在需要它的地方

因此,您在这里的第一步:

去掉
@Inject
并添加一个构造函数,该构造函数设置
测试服务
——最好将变量设置为final,以便在未在命令中设置时,所有警报都会发出

现在,如果您通过
new
创建
TestWorker
,您将被迫通过
TestService
(您仍然可以通过
null
等,但断言可以强制执行)


另一个选项(不管您是切换到基于c'tor的注入,还是出于某种原因仍要使用
@Inject
),都是要求
应用程序上下文构建您的实例。例如,
applicationContext.getBean(Testworker)

问题是您正在使用位于的
new Testworker()
创建一个worker实例。执行此操作时,不涉及依赖项注入容器,因此该实例将不会进行依赖项注入,因此
testWorker
属性在
TestManager
的特定实例上将为空


建议对设计进行改进需要了解周围的环境,但上面解释了为什么您会得到NPE。

使用@Inject在我的书中是一种代码味道,这里我们来看看原因。“-@注入不是问题的一部分。问题是,应用程序正在处理在DI容器外部创建的
TestWorker`实例,因此该实例没有受到DI的约束。如果您使用的是
@Inject
,或者没有使用,那就对了。@JeffScottBrown您可能错过了最后一段。“您可能错过了最后一段。”-我不这么认为。我读了最后一段。我刚才又读了一遍。那一段描述了另一个有不同问题的选项,但我确实读过,我不认为我读错了。也许是的,谢谢。关于applicationContext.getBean(TestWorker.class)的用法,如果有一个构造函数具有类似TestWorker(String foo)的参数,我应该如何使用applicationContext.getBean(TestWorker.class)并向构造函数中注入一个变量?除非字符串来自@Value,否则我怀疑您是否可以。但不要认为我是这方面的专家。