从应用程序作用域Bean

时间:2016-02-03 02:10:10

标签: jsf dependency-injection cdi

如果我有@ApplicationScoped bean仅在@PostConstruct方法中使用注入,那么:

@Named
@ApplicationScoped
public class CountriesConverter implements Converter {
    private List<Country> countries;

    @Inject
    private CountriesService cs;

    @PostConstruct
    public void init() {
        this.countries = cs.getAllCountries();
    }
 ...
}

这是否意味着bean不必要地持有不必要的依赖?在注入请求数据库的服务的情况下,这是否意味着池中只有一个服务对象?值得担心吗?如果是这样,我可以释放依赖吗?

1 个答案:

答案 0 :(得分:3)

cs字段的运行时内容取决于CountriesService的范围。如果它在正常范围内(@ApplicationScoped,@ RequestScoped,@ SessionScoped等),你将拥有一个代理而不是具体对象。如果它是假镜(@Dependent或根本没有注释,或自定义范围),那么你最终得到了该类的具体实例。

如果您有代理,则每次调用代理中的方法时,CDI容器都将检索相应的上下文实例并将请求委托给该对象。如果范围不包含适用的对象,则将创建一个新对象并将其放入上下文中,然后将请求委派给该对象。在销毁上下文(请求结束,http会话结束等)时,对象会被清理。

解决具体问题:

  

这是否意味着bean不必要地持有不必要的东西   依赖?

如果CountriesService是依赖bean,是的。在这种情况下,您可以在完成后将字段设置为null,或者注入实例而不是对象本身。

@Inject
private Instance<CountriesService> serviceInstance;

@PostConstruct
private void init() {
    this.countries = serviceInstance.get().getAllCountries();
}
  

在注入请求数据库的服务的情况下,这是否意味着池中只有一个服务对象?

池的概念不适用于CDI bean。在这个意义上没有池,CDI根本不关心并发性。如果您正在使用无状态EJB,那么您有一个指向池的代理,因此您仍然可以。

  

值得担心吗?

很可能不是。如果CountriesService是一个庞大的,依赖范围的bean,那么可能,但在这种情况下,您的架构可能有问题:)