managedproperty spring jsf dependency-injection integration managed-bean

managedproperty - Integración Spring JSF: ¿cómo inyectar un componente/servicio Spring en un bean gestionado JSF?



@managedproperty (3)

@Controller vs @Controller

En primer lugar, debe elegir un marco para administrar sus granos. Debe elegir JSF o Spring (o CDI) para administrar sus beans. Mientras que el siguiente funciona, es fundamentalmente incorrecto:

@ManagedBean // JSF-managed. @Controller // Spring-managed. public class BadBean {}

Usted termina con dos instancias completamente separadas de la misma clase de bean administrado, una administrada por JSF y otra administrada por Spring. No está claro cuál se usará realmente en EL cuando lo referencia como #{someBean} . Si tiene SpringBeanFacesELResolver registrado en faces-config.xml , entonces será el administrado por Spring, no el manejado por JSF. Si no tienes eso, entonces sería el administrado por JSF.

Además, cuando declara un ámbito específico de bean gestionado JSF, como @RequestScoped , @ViewScoped , @SessionScoped o @ApplicationScoped del paquete javax.faces.* , Solo será reconocido y utilizado por @ManagedBean . No será entendido por @Controller ya que espera su propia anotación @Scope . Esto está predeterminado en singleton (ámbito de aplicación) cuando está ausente.

@ManagedBean // JSF-managed. @ViewScoped // JSF-managed scope. @Controller // Spring-managed (without own scope, so actually becomes a singleton). public class BadBean {}

Cuando hace referencia al bean anterior a través de #{someBean} , devolverá el bean con ámbito administrado por Spring, no el bean con ámbito de vista administrado por JSF.

@Autowired vs. @Autowired

La @ManagedProperty específica de JSF solo funciona en beans administrados por JSF, es decir, cuando usa @ManagedBean . El @Autowired específico de @Autowired funciona solo en beans gestionados por Spring, es decir, cuando usa @Controller . Los enfoques a continuación son menos o más equivalentes y no se pueden combinar:

@ManagedBean // JSF-managed. @RequestScoped // JSF-managed scope. public class GoodBean { @ManagedProperty("#{springBeanName}") private SpringBeanClass springBeanName; // Setter required. }

@Component // Spring-managed. @Scope("request") // Spring-managed scope. public class GoodBean { @Autowired private SpringBeanClass springBeanName; // No setter required. }

Tenga en cuenta que cuando tiene SpringBeanFacesELResolver registrado en faces-config.xml según el SpringBeanFacesELResolver ,

<application> ... <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> </application>

y por lo tanto, puede hacer referencia a los beans administrados por Spring en EL a través de #{springBeanName} , luego también puede hacer referencia a ellos en @ManagedProperty , ya que básicamente establece el resultado evaluado de la expresión EL dada. A la inversa, inyectar un bean gestionado JSF a través de @Autowired , de ninguna manera es compatible. Sin embargo, puede utilizar @Autowired en un bean administrado JSF cuando registra manualmente la instancia de bean administrada JSF en el contexto autowirable de Spring como se muestra a continuación. Vea también Cómo integrar JSF 2 y Spring 3 (o Spring 4) muy bien para el truco.

@ManagedBean // JSF-managed. @ViewScoped // JSF-managed scope. public class GoodBean implements Serializable { @Autowired private SpringBeanClass springBeanName; // No setter required. @PostConstruct private void init() { FacesContextUtils .getRequiredWebApplicationContext(FacesContext.getCurrentInstance()) .getAutowireCapableBeanFactory().autowireBean(this); // springBeanName is now available. } }

@XxxScoped vs @Scope

Spring @Scope tiene soporte limitado para los ámbitos JSF. No hay un equivalente para @ViewScoped de JSF. Básicamente, harías homegrow tus propios ámbitos, o te apegarías al registro manual de la instancia de bean administrada JSF en el contexto autowirable de Spring, como se muestra arriba.

Y, desde el otro lado, Spring WebFlow fue asumido en JSF 2.2 a través de la nueva anotación @FlowScoped . Entonces, si ya está en JSF 2.2, no necesariamente necesita usar Spring WebFlow si solo desea el alcance del flujo.

CDI - tratando de unificarlo todo

Desde Java EE 6, CDI se ofrece como alternativa estándar a Spring DI. Tiene anotaciones respectivamente @Named e @Inject para esto y también su propio conjunto de ámbitos. No estoy seguro de cómo interactúa con Spring ya que no utilizo Spring, pero @Inject funciona dentro de @Inject , y @ManagedProperty dentro de @ManagedBean puede hacer referencia a un bean @Named . Por otro lado, @ManagedProperty no funciona dentro de un bean @Named .

El objetivo de CDI es unificar todos los diferentes marcos de gestión de beans en una sola especificación / interfaz. Spring podría haber sido una implementación completa de CDI, pero eligieron implementarlo solo parcialmente (solo se javax.inject.* JSR-330 javax.inject.* , Pero JSR-299 javax.enterprise.context.* No). Ver también ¿Will Spring es compatible con CDI? y este tutorial

JSF se mudará a CDI para la administración de frijoles y depreciará @ManagedBean y sus amigos en una versión futura.

Ver también:

Entiendo que un bean administrado funciona como un controlador, porque su única tarea es "vincular" la capa de vista con el modelo.

Para usar un bean como un bean administrado, debo declarar la anotación @ManagedBean , haciendo eso puedo comunicar JSF con bean directamente.

Si quiero inyectar algún componente (desde Spring) en este managedBean, tengo dos formas posibles:

  1. Elija la propiedad en ManagedBean (como "BasicDAO dao") y declare @ManagedProperty(#{"basicDAO"}) sobre la propiedad. Al hacerlo, inyectaré el bean "basicDAO" de Spring en ManagedBean.

  2. Declarado @Controller en ManagedBean Class, entonces tendré @Controller y @Controller anotaciones, todas juntas. Y en la propiedad "BasicDAO dao" debo usar @Autowired de Spring.

Es mi entendimiento correcto?


Hay otra manera de usar beans administrados por Spring en beans administrados por JSF simplemente extendiendo su bean JSF desde SpringBeanAutowiringSupport y Spring manejará la inyección de dependencia.

@ManagedBean // JSF-managed. @ViewScoped // JSF-managed scope. public class GoodBean extends SpringBeanAutowiringSupport { @Autowired private SpringBeanClass springBeanName; // No setter required. // springBeanName is now available. }


La forma más fácil de hacerlo es a través de XML. @Component en @Component administrados @Component ya creados, pero @Autowired no funcionó porque el bean administrado ya estaba allí en faces-config.xml. Si es obligatorio mantener esa definición de beans administrados junto con su propiedad administrada en el archivo xml, se sugiere agregar el bean de primavera como otra propiedad administrada dentro de la etiqueta de bean administrada. Aquí el bean de primavera está definido allí en spring-config.xml (se puede autoconectar en algún lugar de forma alternativa). Por favor, consulte https://.com/a/19904591/5620851

editado por mí. Sugiero implementarlo completamente a través de la anotación @Managed y @Component o vía xml para ambos.