CDI 中的@ManagedBean(eager=true) 等价于什么
What is the equivalent of @ManagedBean(eager=true) in CDI
众所周知,建议使用 javax.enterprise.context
中的注释而不是 javax.faces.bean
,因为它们已被弃用。
我们都发现 ManagedBeans 带有 eager="true"
注释 @ApplicationScoped
来自 javax.faces.bean
并且具有 @PostConstruct
方法对于进行 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.
}
...
}
我想知道的是,如果我使用 javax.enterprise.context
.
中的注释,我如何才能获得相同的行为
注:
来自 javax.ejb
的 @Startup
注释将有助于 运行 该代码,但仅在应用程序服务器 启动 [=36] 时部署 webapp 的那一刻=].
这不是由 CDI 或 JSF 提供的。您可以使用自定义 CDI 限定符和 ServletContextListener
挂钩 webapp 启动来自行开发。
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Eager {
//
}
@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.
}
}
(注意: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!");
}
}
至于现有库,只有 JSF 实用程序库 OmniFaces offers @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!");
}
}
在 @SessionScoped
、@ViewScoped
和 @RequestScoped
上也是 supported。
无论采用哪种方法,唯一的缺点是 FacesContext
在构建 bean 时不可用。但这应该不是什么大问题,使用 CDI,您可以简单地直接 @Inject
感兴趣的工件,例如 ServletContext
或 HttpSession
.
CDI 1.1 还提供了一种标准方式来观察作用域生命周期事件,例如:
public void processApplicationScopedInit(@Observes @Initialized(ApplicationScoped.class) ServletContext payload) {}
public void processApplicationScopedDestroyed(@Observes @Destroyed(ApplicationScoped.class) ServletContext payload) {}
更多信息:http://www.next-presso.com/2014/06/you-think-you-know-everything-about-cdi-events-think-again/
作为替代方案,您可以使用 EJB 而不是 CDI。然后你可以有一个 @Singleton
和 @Startup
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 {}
现在您可以在没有任何额外限定符的情况下注入此 CDI bean:
@Inject
private SomeCdiBean someCdiBean;
众所周知,建议使用 javax.enterprise.context
中的注释而不是 javax.faces.bean
,因为它们已被弃用。
我们都发现 ManagedBeans 带有 eager="true"
注释 @ApplicationScoped
来自 javax.faces.bean
并且具有 @PostConstruct
方法对于进行 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.
}
...
}
我想知道的是,如果我使用 javax.enterprise.context
.
注:
来自 javax.ejb
的 @Startup
注释将有助于 运行 该代码,但仅在应用程序服务器 启动 [=36] 时部署 webapp 的那一刻=].
这不是由 CDI 或 JSF 提供的。您可以使用自定义 CDI 限定符和 ServletContextListener
挂钩 webapp 启动来自行开发。
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Eager {
//
}
@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.
}
}
(注意: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!");
}
}
至于现有库,只有 JSF 实用程序库 OmniFaces offers @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!");
}
}
在 @SessionScoped
、@ViewScoped
和 @RequestScoped
上也是 supported。
无论采用哪种方法,唯一的缺点是 FacesContext
在构建 bean 时不可用。但这应该不是什么大问题,使用 CDI,您可以简单地直接 @Inject
感兴趣的工件,例如 ServletContext
或 HttpSession
.
CDI 1.1 还提供了一种标准方式来观察作用域生命周期事件,例如:
public void processApplicationScopedInit(@Observes @Initialized(ApplicationScoped.class) ServletContext payload) {}
public void processApplicationScopedDestroyed(@Observes @Destroyed(ApplicationScoped.class) ServletContext payload) {}
更多信息:http://www.next-presso.com/2014/06/you-think-you-know-everything-about-cdi-events-think-again/
作为替代方案,您可以使用 EJB 而不是 CDI。然后你可以有一个 @Singleton
和 @Startup
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 {}
现在您可以在没有任何额外限定符的情况下注入此 CDI bean:
@Inject
private SomeCdiBean someCdiBean;