|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Componentclass SingletonScopedBean{ @Autowired private PrototypeScopedBean prototypeScopedBean; public String getState(){ return this.prototypeScopedBean.getState(); }}@Component@Scope(value="prototype")class PrototypeScopedBean{ private final String state; public PrototypeScopedBean(){ this.state = UUID.randomUUID().toString(); } public String getState() { return state; }} |
Здесь прототип боба с ограниченным объемом вводится в боб синглтона с ограниченным объемом действия.
Теперь рассмотрим этот тест, используя следующие компоненты:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfigurationpublic class ScopedProxyTest { @Autowired private SingletonScopedBean singletonScopedBean; @Test public void testScopedProxy() { assertThat(singletonScopedBean.getState(), not(equalTo(singletonScopedBean.getState()))); } @Configuration @ComponentScan("org.bk.samples.scopedproxy") public static class SpringContext{}} |
Следует отметить, что здесь создается только 1 экземпляр PrototypeScopedBean, и этот 1 экземпляр внедряется в SingletonScopedBean, поэтому приведенный выше тест, который фактически ожидает новый экземпляр PrototypeScopedBean при каждом вызове метода getState (), завершится неудачно. ,
Если при каждом запросе к PrototypeScopedBean требуется новый экземпляр (и, как правило, если компонент с более длинной областью имеет компонент с более короткой областью действия в качестве зависимости, и более короткую область необходимо учитывать), то существует несколько решений:
1. Метод поиска инъекций — о котором можно прочитать здесь
2. Лучшим решением является использование прокси Scoped —
Прокси с заданной областью можно указать таким образом, используя @Configuration:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
@Component@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)class PrototypeScopedBean{ private final String state; public PrototypeScopedBean(){ this.state = UUID.randomUUID().toString(); } public String getState() { return state; }} |
С этим изменением компонент, внедренный в SingletonScopedBean, является не самим PrototypeScopedBean, а посредником для компонента (созданным с использованием CGLIB или динамических прокси-серверов), и этот прокси-сервер понимает область и возвращает экземпляры на основе требований области, тест должен сейчас работаю как положено.
Ссылка: Spring Scoped Proxy от нашего партнера JCG Биджу Кунджуммен в блоге all and sundry.