Java micronaut@RequestScope-不为每个传入http请求创建bean
我有一个类,下面的类是RequestScope bean:Java micronaut@RequestScope-不为每个传入http请求创建bean,java,micronaut,requestcontext,requestscope,micronaut-rest,Java,Micronaut,Requestcontext,Requestscope,Micronaut Rest,我有一个类,下面的类是RequestScope bean: @RequestScope class RequestContext { private String requestId; private String traceId; private String authorisedId; private String routeName; // few more fields @Inject RequestContext(SecurityConte
@RequestScope
class RequestContext {
private String requestId;
private String traceId;
private String authorisedId;
private String routeName;
// few more fields
@Inject RequestContext(SecurityContext securityContext) {
this.requestId = UUID.randomUUID().toString();
if(securityService.getAuthentication().isPresent()){
this.authorisedId = (securityService
.getAuthentication().get()).getUserId().toString();
}
}
/* to be updated in controller method interceptors */
public void updateRouteName(String name){
this.routeName = name;
}
其思想是让一个包含REST请求级别自定义数据的对象可以在整个应用程序中访问,其范围显然应该在当前请求中。这可以用来表示。。日志记录-每当开发人员记录应用程序中的任何内容时,一些请求元数据就会随之出现
我不清楚@RequestScope bean到底是什么:
从它的定义来看——我的假设是,它是为每个新的http请求创建的,并且在该请求的生命周期中共享相同的实例
Micronaut何时建造?它是不变的吗
在多个请求中,我可以看到相同的请求ID(每个请求都需要新的UUID)
它是@RequestScope bean的正确用例吗
Micronaut何时建造
第一次需要bean时,在请求处理期间创建@RequestScope
bean
它是不变的吗
可能是。在编写类时,您可以决定bean是否是可变的。正如在您的示例中所写,RequestContext
是可变的。如果删除updateRouteName
方法,该bean将是不可变的
它是@RequestScope bean的正确用例吗
我不这么认为,但这确实是一个基于意见的问题
编辑:基于下面添加的评论
请参阅上的项目
如果将请求范围的bean注入到单例bean中,则这可能不起作用。在这种情况下,您需要向bean注入Provider@CyrilG. 谢谢你的回复。您能让我进一步了解请求范围的bean是何时第一次创建的吗?试图将提供程序注入到单例bean中,但失败了,出现了一个ununiquebeanexception:找到了多个可能的bean候选者-它们究竟是在什么时候创建的?@cyrig。不确定那是什么错误,似乎已经清除了。但是随着提供程序的注入,每次调用Provider.get()时,它都会创建一个新的RequestContext实例,而不是请求作用域的目的感谢响应。关于不变性,正如您所指出的,我理解编写的类是可变的,但我的问题是,一旦bean在第一次需要时被构造,它似乎就不会在请求范围内的其他地方注入变异对象(updateRouteName)。另外,如何将为新请求创建的实例注入单例bean?“如何将为新请求创建的实例注入单例bean”-所有常用的注入方法word(构造函数、属性或字段)。是的,但是当注入单例bean时,它在整个应用程序生命周期中保留对请求作用域bean的相同引用(当然,因为容器bean本身就是单例的)。因此,它可能需要一个被注入到单例容器bean中的请求范围bean的代理,并且该代理应该能够对当前请求的请求范围bean进行操作。虽然“是的,但是当注入到一个单例bean中时,它在整个应用程序生命周期中保留对请求范围bean的相同引用”,但我不确定如何实现这一点——我认为这是不正确的。“t也许应该为注入到单例容器bean中的请求范围bean创建一个代理,并且该代理应该能够对当前请求的请求范围bean进行操作。”-这就是发生的情况。请参阅上的项目。在的测试表明请求作用域正在工作。
package rscope;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
@Controller("/")
public class DemoController {
private final DemoBean demoBean;
public DemoController(DemoBean demoBean) {
this.demoBean = demoBean;
}
@Get("/doit")
public String doit() {
return String.format("Bean identity: %d", demoBean.getBeanIdentity());
}
}
package rscope;
import io.micronaut.runtime.http.scope.RequestScope;
@RequestScope
public class DemoBean {
public DemoBean() {
}
public int getBeanIdentity() {
return System.identityHashCode(this);
}
}
package rscope;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@MicronautTest
public class DemoControllerTest {
@Inject
@Client("/")
RxHttpClient client;
@Test
public void testIndex() throws Exception {
// these will contain the identity of the the DemoBean used to handle these requests
String firstResponse = client.toBlocking().retrieve("/doit");
String secondResponse = client.toBlocking().retrieve("/doit");
assertTrue(firstResponse.matches("^Bean identity: \\d*$"));
assertTrue(secondResponse.matches("^Bean identity: \\d*$"));
// if you modify DemoBean to be @Singleton instead of
// @RequestScope, this will fail because the same instance
// will be used for both requests
assertNotEquals(firstResponse, secondResponse);
}
}