bean proxy com escopo de primavera

98

Alguém pode explicar o uso da @ScopedProxyanotação de mola ? Eu pensei que tinha algo a ver com escopo de sessão feijão, mas eu não tenho certeza do que.

No meu uso de escopos, usei beans com escopo de sessão sem a @ScopedProxyanotação (ou sem proxies com escopo aop), então tenho certeza de como usá-lo corretamente.

Jeff Storey
fonte
verifique a documentação do bean . A sessão é um dos escopos , mas não o único.
Gus
1
@Gus, estou ciente dos escopos, mas não tenho certeza de como o proxy com escopo atua nisso
Jeff Storey
1
A seção 3.4.4.5 é, em minha opinião, uma boa explicação do que um proxy com escopo faz. - o bit entre os dois exemplos é a parte importante.
Gus
2
Sim, isso explica tudo, obrigado. Se você quiser adicionar uma resposta à pergunta, eu aceito.
Jeff Storey de

Respostas:

248

A seção 3.4.4.5 dos documentos de primavera explica muito bem:

(observe que a seguinte definição de bean 'userPreferences' como está está incompleta):

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

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

A partir da configuração acima, é evidente que o bean singleton 'userManager' está sendo injetado com uma referência ao bean com escopo de sessão HTTP 'userPreferences'. O ponto saliente aqui é que o bean 'userManager' é um singleton ... ele será instanciado exatamente uma vez por contêiner , e suas dependências (neste caso apenas um, o bean 'userPreferences') também serão injetadas (uma vez! ) .

Isso significa que o 'userManager' irá (conceitualmente) operar apenas no mesmo objeto 'userPreferences', que é aquele com o qual foi originalmente injetado.

Isso não é o que você quer quando injeta um bean com escopo de sessão HTTP como uma dependência em um objeto de colaboração (normalmente). Em vez disso, o que queremos é um único objeto 'userManager' por contêiner e, então, durante o tempo de vida de uma Sessão HTTP, queremos ver e usar um objeto 'userPreferences' específico para a referida Sessão HTTP .

Em vez disso, o que você precisa é injetar algum tipo de objeto que exponha exatamente a mesma interface pública que a classe UserPreferences (de preferência um objeto que seja uma instância de UserPreferences) e que seja inteligente o suficiente para poder ir buscar o objeto UserPreferences real de qualquer mecanismo de escopo subjacente que escolhemos (solicitação HTTP, sessão, etc.). Podemos então injetar com segurança esse objeto proxy no bean 'userManager', que felizmente não perceberá que a referência UserPreferences que está segurando é um proxy .

Em nosso caso, quando uma instância do UserManager invoca um método no objeto UserPreferences injetado por dependência, ela realmente invoca um método no proxy ... o proxy então dispara e busca o objeto UserPreferences real (neste caso) a Sessão HTTP e delegar a invocação do método ao objeto UserPreferences real recuperado.

É por isso que você precisa da seguinte configuração correta e completa ao injetar beans com escopo request-, session- e globalSession em objetos de colaboração:

<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>
Gus
fonte
Então, quando eu uso a anotação @ScopedProxy, um Proxy será usado automaticamente, e isso é tudo? ScopedProxy significa -> Não usar esta classe como ela é, usar um proxy para ela?
Koray Tugay
3
Estou usando o spring-web: 4.3.3 e parece que a anotação @ScopedProxyfoi substituída por @RequestScopee outros. Você pode encontrar exemplos aqui: logicbig.com/tutorials/spring-framework/spring-core/…
adebasi
1
Poderíamos dizer que quando a notação @Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)é usada, SpringMVC não usa WebApplicationContext para Autowired, em vez disso, usa CGLIB para criar o proxy ?. Aqui outra explicação com exemplos fora
Kurapika
0

Depois de experimentar várias opções diferentes especificadas aqui e a documentação do Spring, descobri por algum motivo que o Spring MVC é um controlador estranhamente autowiring quando você usa a anotação @Controller e onde você tem mais de um controlador em seu webapp. Modificada a anotação para @RestController (value = "UniqueControllerv1"), o problema foi resolvido.

geeksquad87
fonte