Integrazione JSF di Spring: come iniettare un componente / servizio Spring nel bean gestito JSF?

Capisco che un bean gestito funzioni come un controller, perché il tuo unico compito è “colbind” il View Layer con Model.

Per utilizzare un bean come bean gestito, devo dichiarare l’annotazione @ManagedBean , in modo da poter comunicare direttamente JSF con bean.

Se voglio iniettare alcuni componenti (da Spring) in questo bean gestito ho due modi possibili:

  1. Scegli la proprietà in ManagedBean (come “BasicDAO dao”) e dichiara @ManagedProperty(#{"basicDAO"}) sopra la proprietà. "basicDAO" , sto iniettando il bean "basicDAO" da Spring in ManagedBean.

  2. Dichiarato @Controller nella class ManagedBean, quindi avrò annotazioni @ManagedBean e @Controller , tutte insieme. E nella proprietà "BasicDAO dao" devo usare @Autowired di Spring.

La mia comprensione è corretta?

Esiste un altro modo per utilizzare i bean gestiti da Spring nei bean gestiti da JSF estendendo semplicemente il bean JSF da SpringBeanAutowiringSupport e Spring gestirà l’iniezione delle dipendenze.

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

@ManagedBean vs @Controller

Prima di tutto, dovresti scegliere un framework per gestire i tuoi bean. Dovresti scegliere JSF o Spring (o CDI) per gestire i tuoi bean. Mentre il seguente funziona, è fondamentalmente sbagliato:

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

Finisci con due istanze completamente separate della stessa class di bean gestita, una gestita da JSF e un’altra gestita da Spring. Non è chiaro quale sarà effettivamente usato in EL quando si fa riferimento a #{someBean} . Se si dispone di SpringBeanFacesELResolver registrato in faces-config.xml , sarà gestito da Spring e non da JSF. Se non lo hai, allora sarà gestito da JSF.

Inoltre, quando dichiari un ambito specifico per bean gestito JSF, come @RequestScoped , @ViewScoped , @SessionScoped o @ApplicationScoped dal pacchetto javax.faces.* , Verrà riconosciuto e utilizzato solo da @ManagedBean . Non verrà compreso da @Controller in quanto prevede la propria annotazione @Scope . Il valore predefinito è Singleton (ambito applicazione) quando assente.

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

Quando fai riferimento al bean precedente tramite #{someBean} , restituisce il bean con ambito applicazione gestito da Spring, non il bean con ambito di visualizzazione gestito da JSF.


@ManagedProperty vs @Autowired

La proprietà @ManagedProperty specifica per JSF funziona solo in bean gestiti da JSF, ad esempio quando si utilizza @ManagedBean . @Autowired specifico per @Autowired funziona solo con bean gestiti da Spring, ovvero quando stai usando @Controller . Gli approcci sottostanti sono meno o più equivalenti e non possono essere mischiati:

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

Si noti che quando SpringBeanFacesELResolver registrato in faces-config.xml come da javadoc ,

  ... org.springframework.web.jsf.el.SpringBeanFacesELResolver  

e quindi puoi fare riferimento ai bean gestiti da Spring in EL tramite #{springBeanName} , quindi puoi semplicemente farli riferimento anche in @ManagedProperty , poiché in pratica imposta il risultato valutato della specifica espressione EL. Al contrario, l’iniezione di un bean gestito JSF tramite @Autowired non è supportata in alcun modo. Tuttavia, è ansible utilizzare @Autowired in un bean gestito JSF quando si registra manualmente l’istanza del bean gestito JSF nel contesto autowirable di Spring come di seguito. Vedi anche Come integrare JSF 2 e Spring 3 (o Spring 4) per il trucco.

 @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’s @Scope ha un supporto limitato per gli ambiti JSF. Non esiste un equivalente per @ViewScoped di JSF. Fondamentalmente, potresti decidere di modificare i propri ambiti, o limitarti a registrare manualmente l’istanza del bean gestito da JSF nel contesto di Spring come mostrato sopra.

E dall’altra parte, Spring WebFlow è stata rilevata in JSF 2.2 tramite la nuova annotazione @FlowScoped . Quindi, se ti trovi già su JSF 2.2, non devi necessariamente utilizzare Spring WebFlow se desideri unicamente l’ambito del stream.


CDI – cercando di unificare tutto

Dal momento che Java EE 6, CDI è offerto come alternativa standard a Spring DI. Ha rispettivamente annotazioni @Named e @Inject per questo e anche il proprio set di ambiti. Non sono sicuro di come interagisca con Spring poiché non utilizzo Spring, ma @Inject funziona all’interno di @ManagedBean e @ManagedProperty all’interno di @ManagedBean può fare riferimento a un bean @Named . D’altra parte, @ManagedProperty non funziona all’interno di un bean @Named .

Lo scopo del CDI è di unificare tutti i diversi framework di gestione dei bean in una sola specifica / intefaccia. Spring avrebbe potuto essere un’implementazione completa del CDI, ma hanno scelto di implementarla solo parzialmente (solo JSR-330 javax.inject.* È supportato, ma JSR-299 javax.enterprise.context.* ). Vedi anche Will Spring support CDI? e questo tutorial .

JSF passerà a CDI per la gestione dei bean e deprecherà @ManagedBean e gli amici in una versione futura.

Guarda anche:

  • Quando è necessario o conveniente utilizzare Spring o EJB3 o tutti insieme?
  • Livello servizio JSF
  • Backing beans (@ManagedBean) o CDI Beans (@Named)?
  • Utilizzo di JSF come tecnologia di visualizzazione di Spring MVC
  • Come installare e utilizzare CDI su Tomcat?

Il modo più semplice per farlo è tramite XML. Ho usato @Component nel bean gestito da @Component già fatto ma @Autowired non ha funzionato perché il bean gestito era già presente in faces-config.xml. Se è obbligatorio mantenere la definizione del bean gestito insieme alla sua proprietà gestita nel file xml, si suggerisce di aggiungere il bean spring come un’altra proprietà gestita all’interno del tag bean gestito. Qui il bean spring è definito in spring-config.xml (può essere triggersto da qualche parte in modo alternato). si prega di consultare https://stackoverflow.com/a/19904591/5620851

a cura di me. Suggerisco di implementarlo del tutto tramite l’annotazione @Managed e @Component o tramite xml per entrambi.