Jsf CDI中@ManagedBean(eager=true)的等价物是什么

Jsf CDI中@ManagedBean(eager=true)的等价物是什么,jsf,jakarta-ee,cdi,managed-bean,eager-loading,Jsf,Jakarta Ee,Cdi,Managed Bean,Eager Loading,我们都知道,建议使用javax.enterprise.context中的注释,而不是javax.faces.bean,因为它们越来越不受欢迎 我们都发现,带有eager=“true”注释的ManagedBeans(来自javax.faces.bean的@ApplicationScoped)和@PostConstruct方法对web应用程序初始化非常有用,例如:从文件系统读取属性,初始化数据库连接等 示例: 我想知道的是,如果我使用了javax.enterprise.context中的注释,如何获

我们都知道,建议使用
javax.enterprise.context
中的注释,而不是
javax.faces.bean
,因为它们越来越不受欢迎

我们都发现,带有
eager=“true”
注释的ManagedBeans(来自
javax.faces.bean的
@ApplicationScoped
)和
@PostConstruct
方法对web应用程序初始化非常有用,例如:从文件系统读取属性,初始化数据库连接等

示例:

我想知道的是,如果我使用了
javax.enterprise.context
中的注释,如何获得相同的行为

注意:
来自
javax.ejb
@Startup
注释将有助于运行该代码,但仅在部署webapp时,当应用程序服务器启动时,CDI或JSF不提供该注释。您可以使用自定义CDI限定符和挂接webapp start的to来实现自己的HomeGrowth

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Eager {
    //
}

对于现有的库,只有JSF实用程序库提供了开箱即用的功能

import org.omnifaces.cdi.Eager;
import javax.enterprise.context.ApplicationScoped;

@Eager
@ApplicationScoped
public class YourEagerApplicationScopedBean {

    @PostConstruct
    public void init() {
        System.out.println("Application scoped init!");
    }
}
它也在
@SessionScoped
@ViewScoped
@RequestScoped


不管采用哪种方法,唯一的缺点是
FacesContext
在构建bean时不可用。但这不应该是一个大问题,使用CDI,您可以直接
@注入感兴趣的工件,例如
ServletContext
HttpSession
,CDI 1.1还提供了观察范围生命周期事件的标准方法,例如:

public void processApplicationScopedInit(@Observes @Initialized(ApplicationScoped.class) ServletContext payload) {}
public void processApplicationScopedDestroyed(@Observes @Destroyed(ApplicationScoped.class) ServletContext payload) {}

有关更多信息:

作为替代方案,您可以使用EJB而不是CDI。然后你就可以用@Startup创建一个@Singleton

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
public class SomeBean {

    @PostConstruct
    public void init(){
        //Do all needed application initialization.
    }
    ...
}

以下是我使用的一种方法:

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Inject;

@Startup
@Singleton
public class AppStartup
{
    @Inject
    private BeanManager beanManager;

    @PostConstruct
    public void init()
    {       
        // enforce initializing eager CDI beans
        var beans = beanManager.getBeans(Object.class, new AnnotationLiteral<Any>(){});
        for(var bean : beans)
        {
            if(bean.getBeanClass().getAnnotation(Eager.class) != null && bean.getBeanClass().getAnnotation(ApplicationScoped.class) != null)
            {
                var beanProxyInstance = beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));

                // invoking toString() on the proxy object will invoke the method annotated with @PostConstruct, if has not been invoked yet
                beanProxyInstance.toString();
            }
        }
    }
}
现在,无需任何额外的限定符即可注入此CDI bean:

@Inject
private SomeCdiBean someCdiBean;

这里有一个问题,应该将限定符
@Eager
添加到注入点。根据你的回答,我在下面发布了一个解决问题的答案。谢谢。如果有人开始使用ejb,那么有一个更简单的解决方案,请参阅另一个答案为什么不使用您建议的bean并注入您迫切需要安装的CDIBean?将类命名为instatitator。
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
public class SomeBean {

    @PostConstruct
    public void init(){
        //Do all needed application initialization.
    }
    ...
}
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Inject;

@Startup
@Singleton
public class AppStartup
{
    @Inject
    private BeanManager beanManager;

    @PostConstruct
    public void init()
    {       
        // enforce initializing eager CDI beans
        var beans = beanManager.getBeans(Object.class, new AnnotationLiteral<Any>(){});
        for(var bean : beans)
        {
            if(bean.getBeanClass().getAnnotation(Eager.class) != null && bean.getBeanClass().getAnnotation(ApplicationScoped.class) != null)
            {
                var beanProxyInstance = beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));

                // invoking toString() on the proxy object will invoke the method annotated with @PostConstruct, if has not been invoked yet
                beanProxyInstance.toString();
            }
        }
    }
}
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target({TYPE})
public @interface Eager {}
import javax.enterprise.context.ApplicationScoped;

@Eager
@ApplicationScoped
public class SomeCdiBean {}
@Inject
private SomeCdiBean someCdiBean;