bean proxy con ambito spring


98

Qualcuno può spiegare l'uso dell'annotazione della molla @ScopedProxy? Ho pensato che avesse qualcosa a che fare con scope sessione fagioli, ma non sono abbastanza sicuro che cosa.

Nel mio utilizzo degli ambiti, ho utilizzato bean con ambito di sessione senza l' @ScopedProxyannotazione (o senza proxy con ambito aop), quindi sono davvero sicuro di come usarlo correttamente.


controlla la documentazione del bean . La sessione è uno degli scopi , ma non l'unico.
Gus

1
@Gus, sono a conoscenza degli ambiti, ma non sono sicuro di come il proxy con ambito giochi in questo
Jeff Storey

1
La sezione 3.4.4.5 è a mio parere una spiegazione abbastanza buona di ciò che fa un proxy con ambito. - la parte tra i due esempi è la parte importante.
Gus

2
Sì, questo lo spiega, grazie. Se vuoi aggiungere una risposta alla domanda, accetto.
Jeff Storey

Risposte:


248

La sezione 3.4.4.5 dei documenti di primavera lo spiega abbastanza bene:

(si noti che la seguente definizione di bean 'userPreferences' così com'è è incompleta):

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

Dalla configurazione precedente è evidente che il bean singleton "userManager" viene iniettato con un riferimento al bean con ambito di sessione HTTP "userPreferences". Il punto saliente qui è che il bean 'userManager' è un singleton ... verrà istanziato esattamente una volta per contenitore , e anche le sue dipendenze (in questo caso solo una, il bean 'userPreferences') verranno iniettate solo (una volta! ) .

Ciò significa che "userManager" funzionerà (concettualmente) sempre e solo sullo stesso identico oggetto "userPreferences", ovvero quello con cui è stato originariamente iniettato.

Questo non è ciò che si desidera quando si inietta un bean con ambito di sessione HTTP come dipendenza in un oggetto collaborante (in genere). Piuttosto, quello che vogliamo è un singolo oggetto "userManager" per contenitore , quindi, per la durata di una sessione HTTP, vogliamo vedere e utilizzare un oggetto "userPreferences" specifico per detta sessione HTTP .

Piuttosto ciò di cui hai bisogno è iniettare una sorta di oggetto che esponga la stessa identica interfaccia pubblica della classe UserPreferences (idealmente un oggetto che è un'istanza di UserPreferences) e che sia abbastanza intelligente da essere in grado di andare a prendere il vero oggetto UserPreferences da qualsiasi meccanismo di scoping sottostante che abbiamo scelto (richiesta HTTP, sessione, ecc.). Possiamo quindi iniettare in modo sicuro questo oggetto proxy nel bean "userManager", che sarà beatamente inconsapevole che il riferimento UserPreferences a cui si tiene è un proxy .

Nel nostro caso, quando un'istanza di UserManager richiama un metodo sull'oggetto UserPreferences inserito nella dipendenza, invocerà davvero un metodo sul proxy ... il proxy si spegnerà e recupererà l'oggetto UserPreferences reale da (in questo caso) la sessione HTTP e delegare la chiamata al metodo sull'oggetto UserPreferences reale recuperato.

Questo è il motivo per cui è necessaria la seguente configurazione, corretta e completa, quando si inseriscono bean con ambito di richiesta, sessione e globalSession negli oggetti collaboranti:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
    <aop:scoped-proxy/>
</bean>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

Quindi, quando utilizzo l'annotazione @ScopedProxy, verrà utilizzato automaticamente un proxy, e questo è tutto? ScopedProxy significa -> Non utilizzare questa classe così com'è, utilizzare un proxy per questo?
Koray Tugay

3
Sto usando spring-web: 4.3.3 e sembra che l'annotazione sia @ScopedProxystata sostituita con @RequestScopee altri. Puoi trovare esempi qui: logicbig.com/tutorials/spring-framework/spring-core/…
adebasi

1
Potremmo dire che quando @Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)viene utilizzata la notazione , SpringMVC non utilizza WebApplicationContext per Autowired, ma utilizza CGLIB per creare il proxy ?. Ecco un'altra spiegazione con esempi fuori
Kurapika

0

Dopo aver provato varie opzioni diverse specificate qui e la documentazione di Spring, ho capito per qualche motivo Spring MVC, è un controller stranamente autowiring quando usi l'annotazione @Controller e dove hai più di uno di questi controller nella tua webapp. Modificata l'annotazione in @RestController (value = "UniqueControllerv1"), il problema è stato risolto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.