que español bean applicationscoped cdi managed-bean

bean - cdi java español



Manera canónica de obtener la instancia de bean administrada por CDI: BeanManager#getReference() versus Context#get() (3)

Pensé que hay dos formas generales de obtener una instancia de BeanManager administrada automáticamente para CDI al tener solo un Bean<T> para comenzar (que se crea en base a Class<T> ):

  1. Por BeanManager#getReference() , que se muestra más a menudo en fragmentos de código:

    Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class)); TestBean testBean1 = (TestBean) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));

  2. Por Context#get() , que se muestra con menos frecuencia en los fragmentos:

    Bean<TestBean> bean = (Bean<TestBean>) beanManager.resolve(beanManager.getBeans(TestBean.class)); TestBean testBean2 = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));

En los efectos, en última instancia, hacen exactamente lo mismo: devolver una referencia por proxy a la instancia actual de bean administrada por CDI y crear automáticamente la instancia de bean si aún no existe en el alcance.

Pero lo hacen de forma un poco diferente: BeanManager#getReference() siempre crea una nueva instancia de proxy, mientras que el Context#get() reutiliza una instancia de proxy existente si ya se creó anteriormente. Esto es evidente cuando el código anterior se ejecuta en un método de acción de una instancia de TestBean existente:

System.out.println(testBean1 == testBean2); // false System.out.println(testBean1 == this); // false System.out.println(testBean2 == this); // true

El Context#get() de Context#get() es muy explícito en esto:

Devuelve una instancia existente de cierto tipo contextual o crea una nueva instancia llamando a Contextual.create (CreationalContext) y devuelve la nueva instancia.

mientras que BeanManager#getReference() de BeanManager#getReference() no es lo suficientemente explícito en esto:

Obtiene una referencia contextual para un cierto frijol y un cierto tipo de frijol del frijol.

Esto me confundió. ¿Cuándo usas uno u otro? En ambos sentidos, necesita una instancia de Bean<T> todos modos, desde la cual la clase de bean y el alcance de bean estén disponibles, lo que se requiere como argumento adicional. No puedo imaginar por qué tendrían que ser suministrados externamente en este caso específico.

Me imagino que Context#get() es más eficiente en cuanto a la memoria, ya que no crea innecesariamente otra instancia de proxy que haga referencia a la misma instancia de bean subyacente, sino que solo encuentra y reutiliza una instancia de proxy existente.

Esto me lleva a la siguiente pregunta: ¿cuándo es más útil BeanManager#getReference() que Context#get() ? Se muestra más a menudo en fragmentos y, a menudo, se recomienda como solución, pero solo crea un proxy nuevo de manera innecesaria, incluso cuando ya existe.


Esto fue muy útil al integrar CDI con javafx, la cuestión es que necesitaba una referencia a la causa del objeto con el objetivo correcto y no el proxy del alcance dependiente ...

Usé un método de productor para obtener un Nodo javaFX que se inyecta en el controlador de esta manera:

@Inject @ApplicationScoped @FXMLFile("javafx/wares.fxml") @FXMLController(WaresController.class) Parent wares;

pero al usar BeanManager # getReference () el proxy que obtengo "come" todos los valores establecidos por el FXMLLoader, el método getContext.get () lo resolvió.

Thnx para esto


Tengo un Singleton al que estaba usando el método getReference () para obtener la referencia. Aunque el singleton ya se había inicializado, el proxy creado a través de getReference () llamaba a @PostConstruct cada vez que se utilizaba getReference ().

@Startup @ApplicationScoped @Singleton @PostConstruct private void initialize() {}

Al cambiar al método getContext (). Get (), las llamadas proxy @PostConstruct innecesarias ya no se realizan.


beanManager # getReference le proporciona una nueva instancia de un cliente proxy, pero el cliente proxy reenviará las llamadas de método a la instancia contextual actual de un contexto particular. Una vez que obtenga el proxy y lo mantenga, las llamadas al método se invocarán en la instancia actual (por ejemplo, solicitud actual). También es útil si la instancia contextual no es serializable: el proxy del cliente se reconectará y se volverá a conectar después de que lo deserialice.

BeanManager # getContext obtiene la instancia de destino sin un proxy de cliente. Todavía puede ver un proxy de Weld en el nombre de la clase, pero esa es una subclase mejorada que proporciona interceptación y decoración. Si el grano no es interceptado ni decorado, será una instancia simple del grano dado.

Usualmente (1) es más adecuado a menos que tenga un caso de uso especial donde necesite acceder directamente a la instancia de destino (por ejemplo, para acceder a sus campos).

O en otras palabras

1) BeanManager # getReference devolverá una ''Referencia contextual'', con un proxy de alcance normal para el bean. Si un bean tiene con @SessionScoped como

@SessionScoped User user;

Luego, el usuario de referencia contextual ''señalará'' a la respectiva instancia de Usuario (la ''Instancia Contextual'') de la sesión actual para cada invocación. Dos invocaciones diferentes a user.getName() desde dos navegadores web diferentes le darán respuestas diferentes.

2) Context # get () devolverá una "Instancia contextual" interna sin el proxy de ámbito normal. Esto generalmente no es nada que un usuario deba llamarse a sí mismo. Si obtiene el User user para "Bob" de esa manera y lo almacena en un bean @ApplicationScoped o en una variable estática, entonces el usuario "Bob" seguirá siendo el mismo, ¡incluso para solicitudes web de otros navegadores! Obtendrás una instancia directa sin proxy.