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

Jal*_*rdo 8 jsf java-ee eager-loading cdi managed-bean

众所周知,建议使用注释javax.enterprise.context而不是javax.faces.bean它们被弃用.

我们都发现eager="true"带有@ApplicationScoped from javax.faces.bean和带有@PostConstruct方法的ManagedBeans 对于Web应用程序初始化非常有用,例如:从文件系统读取属性,初始化数据库连接等等...

示例:

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.annotation.PostConstruct;

@ApplicationScoped
@ManagedBean(eager=true)
public class someBean{

    @PostConstruct
    public void init(){
        //Do all needed application initialization.
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我想知道的是,如果我使用注释,我怎么能得到相同的行为javax.enterprise.context.

注意: @Startup注释fromjavax.ejb将有助于运行该代码,但仅在应用程序服务器启动时部署webapp时.

Bal*_*usC 12

CDI或JSF不提供此功能.你可以使用自定义CDI限定符和一个ServletContextListener挂钩webapp开始自己创建自己的.

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Eager {
    //
}
Run Code Online (Sandbox Code Playgroud)

@WebListener
public class EagerListener implements ServletContextListener{

    private static final AnnotationLiteral<Eager> EAGER_ANNOTATION = new AnnotationLiteral<Eager>() {
        private static final long serialVersionUID = 1L;
    };

    @Override
    public void contextInitialized(ServletContextEvent event) {
        CDI.current().select(EAGER_ANNOTATION).forEach(bean -> bean.toString());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // NOOP.
    }

}
Run Code Online (Sandbox Code Playgroud)

(注意:toString()触发延迟实例化)

import com.example.Eager;
import javax.enterprise.context.ApplicationScoped;

@Eager
@ApplicationScoped
public class YourEagerApplicationScopedBean {

    @PostConstruct
    public void init() {
        System.out.println("Application scoped init!");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

它也支持@SessionScoped,@ViewScoped@RequestScoped.

无论采用何种方法,唯一的缺点是FacesContext在构建bean时不可用.但这不应该是一个大问题,CDI你可以简单地直接@Inject感兴趣的文物,如ServletContextHttpSession.