And*_*niy 1 java java-ee cdi weld
我遇到了以下问题.我正在使用的Weld实现CDI.
我发现如果服务注释了,@ApplicationScoped那么@PostConstruct在第一次使用服务之前不会调用section.这是一个重现此行为的代码:
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.spi.CDI;
public class TestCdi {
public static void main(String[] args) {
try (WeldContainer weldContainer = new Weld().containerId("test").initialize()) {
FooService fooService = CDI.current().select(FooService.class).get();
fooService.test();
System.out.println("Done");
}
}
@ApplicationScoped
public static class FooService {
@PostConstruct
public void init() {
System.out.println("Post construct");
}
public void test() {
System.out.println("test");
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果fooService.test();被注释,则FooService.init()不会被调用.但删除@ApplicationScoped它再次工作!
这对我来说似乎很奇怪,我无法找到和描述这种行为.
此外,规范javax.inject.Provider.get()说:
提供完全构造和注入的T实例.
那么,问题是什么?它是这样设计还是这个bug?对我来说更重要的是:如何绕过这个问题?我需要我的服务@ApplicationScoped.
你所看到的是Weld懒惰的bean初始化方法.对于所有正常的作用域bean(除了@DependentCDI提供的作用域之外的任何东西),实际上你注入了一个委托,它将调用委托给上下文实例.在您尝试在该代理上调用任何bean方法之前,不会创建上下文实例.
CDI规范并没有要求bean渴望或懒惰,这是基于实现的选择(我不确定Weld docs现在是否提到这一点).在Weld的情况下,这主要是性能选择,因为许多bean将被初始化为什么(例如从未使用过),并且它会大大减慢引导速度.
请注意,这不是一个不一致的状态,它对于Weld提供的每个范围都是这样的.它也不是一个矛盾,javax.inject.Provider.get()因为它没有声明@PostConstruct必须在返回实例之前调用它.此外,您实际获得的实例是代理实例,并且无论如何都要完全初始化.
所以它归结为懒惰与急切初始化的一般问题,哪个更好和/或感觉更自然.
至于"解决方案":
@javax.ejb.Singleton并使用@Startup注释.如果您@ApplicationScoped当时处于EE环境中,那么它的表现非常相似.ping()在@ApplicationScopedbean 上创建一个虚方法,并在应用程序启动后立即调用它.这将强制创建bean,从而调用@PostConstruct- 就像你test()在上面的代码示例中使用方法一样.作为旁注 - 在您的示例中,@Inject构造函数上的注释没有用.只有具有参数的构造函数才需要它.
| 归档时间: |
|
| 查看次数: |
2321 次 |
| 最近记录: |