Что такое эквивалент @ManagedBean (Eight=true) в CDI
Как мы все знаем, рекомендуется использовать аннотации из javax.enterprise.context
вместо javax.faces.bean
, поскольку они становятся устаревшими.
И мы все нашли ManagedBeans с eager="true"
аннотацией @ApplicationScoped
из javax.faces.bean
и имеющие метод @PostConstruct
очень полезны для инициализации веб-приложений, например: чтение свойств из файловой системы, инициализация соединений с базой данных и т. д...
пример :
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
.
Примечание:
@Startup
аннотация из javax.ejb
поможет запустить этот код, но только в момент развертывания webapp, когда сервер приложенийстарты.
3 ответа:
Это не предусмотрено CDI или JSF. Вы можете вырастить свой собственный с помощью пользовательского квалификатора CDI и
ServletContextListener
чтобы зацепить webapp start.@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 utility library 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!"); } }
Он также поддерживается на
@SessionScoped
,@ViewScoped
и@RequestScoped
.Независимо от подхода, только недостатком является то, что
FacesContext
не доступен в момент построения Боба. Но это не должно быть большой проблемой, с CDI вы можете просто напрямую@Inject
артефакты интереса, такие какServletContext
илиHttpSession
.
CDI 1.1 также предлагает стандартный способ наблюдения событий жизненного цикла scope, например:
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. } ... }