Что такое эквивалент @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 5

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.
    }
    ...
}