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;