прокси-компонент с весенней областью видимости

98

Может кто-нибудь объяснить использование @ScopedProxyаннотации spring ? Я думал, что это как-то связано с bean-компонентами с областью действия сеанса, но я не совсем уверен, что именно.

При использовании областей видимости я использовал bean-компоненты с областью действия сеанса без @ScopedProxyаннотации (или без прокси с областью действия aop), поэтому я действительно уверен, как использовать ее правильно.

Джефф Стори
источник
ознакомьтесь с документацией по bean . Сессия - одна из сфер , но не единственная.
Gus
1
@Gus, я знаю об объемах, просто не уверен, как прокси с ограниченным объемом играет в этом
Джефф Стори
1
Раздел 3.4.4.5 , на мой взгляд, является довольно хорошим объяснением того, что делает прокси с ограниченной областью действия. - бит между двумя примерами - важная часть.
Gus
2
Да, это все объясняет, спасибо. Если вы хотите добавить ответ на вопрос, я приму.
Джефф Стори

Ответы:

249

Раздел 3.4.4.5 документации Spring довольно хорошо объясняет это:

(обратите внимание, что следующее определение bean-компонента userPreferences в его нынешнем виде является неполным):

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

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

Из приведенной выше конфигурации очевидно, что одноэлементный bean-компонент userManager вводится со ссылкой на HTTP-компонент userPreferences в области сеанса. Важным моментом здесь является то, что bean-компонент userManager является синглтоном ... он будет создан ровно один раз для каждого контейнера , и его зависимости (в данном случае только один bean-компонент userPreferences) также будут введены только (один раз! ) .

Это означает, что «userManager» (концептуально) будет всегда работать только с одним и тем же объектом «userPreferences», то есть с тем, с которым он был изначально введен.

Это не то, что вы хотите, когда вы вставляете bean-компонент с областью действия HTTP в качестве зависимости в сотрудничающий объект (обычно). Скорее, нам действительно нужен один объект userManager для каждого контейнера , а затем, в течение всего времени существования сеанса HTTP, мы хотим видеть и использовать объект userPreferences, специфичный для указанного сеанса HTTP .

Вместо этого вам нужно внедрить какой-то объект, который предоставляет тот же самый открытый интерфейс, что и класс UserPreferences (в идеале объект, который является экземпляром UserPreferences), и который достаточно умен, чтобы иметь возможность уйти и получить реальный объект UserPreferences из любого выбранного механизма определения области видимости (HTTP-запрос, сеанс и т. д.). Затем мы можем безопасно внедрить этот прокси-объект в bean-компонент userManager, который будет блаженно не знать, что ссылка UserPreferences, на которой он держится, является прокси .

В нашем случае, когда экземпляр UserManager вызывает метод в объекте UserPreferences, внедренном зависимостями, он действительно будет вызывать метод на прокси ... затем прокси отключится и получит реальный объект UserPreferences из (в этом случае) HTTP-сеанс и делегируйте вызов метода полученному реальному объекту UserPreferences.

Вот почему вам нужна следующая, правильная и полная конфигурация при внедрении bean-компонентов с областью действия запроса, сеанса и globalSession в взаимодействующие объекты:

<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>
Гас
источник
Итак, когда я использую аннотацию @ScopedProxy, автоматически будет использоваться прокси, и это все? ScopedProxy означает -> Не использовать этот класс как есть, использовать для него прокси?
Корай Тугай
3
Я использую spring-web: 4.3.3, и похоже, что аннотация @ScopedProxyбыла заменена на @RequestScopeи другие. Вы можете найти примеры здесь: logicbig.com/tutorials/spring-framework/spring-core/…
adebasi
1
Можно сказать, что при использовании нотации @Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)SpringMVC не использует WebApplicationContext для Autowired, а вместо этого использует CGLIB для создания прокси ?. Здесь другое объяснение с примерами , выполненными
Kurapika
0

Опробовав различные варианты, указанные здесь, и весеннюю документацию, я по какой-то причине понял, что Spring MVC - это странный контроллер автоподключения, когда вы используете аннотацию @Controller и у вас есть более одного такого контроллера в вашем веб-приложении. Изменена аннотация на @RestController (value = "UniqueControllerv1"), проблема решена.

geeksquad87
источник