Отказ от ответственности: Я прочитал следующий полезный персонал о динамическом прокси JDK и CGLIB: https://stackoverflow.com/a/21762454/2674303
Я прочитал следующую интересную статью: Инъекция бина Spring Prototypeв синглтон бин
Первый случай:
Прототип:
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
class MessageBuilder {
private static final AtomicInteger instanceCounter = new AtomicInteger(0);
MessageBuilder() {
instanceCounter.incrementAndGet();
}
static int getInstanceCounter() {
return instanceCounter.get();
}
....
}
Синглтон:
@Service
class MessageService {
private final MessageBuilder messageBuilder;
MessageService(MessageBuilder messageBuilder) {
this.messageBuilder = messageBuilder;
}
Message createMessage(String content, String receiver) {
return messageBuilder
.withContent(content)
.withReceiver(receiver)
.build();
}
}
Тест:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MessageServiceTest {
@Autowired
private MessageService messageService;
@Test
public void shouldCreateTwoBuilders() throws Exception {
//when
messageService.createMessage("text", "alice");
messageService.createMessage("msg", "bob");
//then
int prototypeCounter = MessageBuilder.getInstanceCounter();
assertEquals("Wrong number of instances", 2, prototypeCounter);
}
}
Очевидно, что тест не пройден, потому что инъекция происходит только один раз, и фактический результат будет 1, но мы ожидали 2.
Второй случай:
Singleton и Test одинаковы, но прототип теперь выглядит следующим образом (proxyMode был изменен):
@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.TARGET_CLASS)
class MessageBuilder {
// ...
}
Когда мы начинаем наш тест, мы видим, что фактический результат равен 6 , поскольку изнутри createMessage
метод messageBuilder доступен 3 раза.и createMessage
метод вызывается дважды, поэтому 3 * 2 = 6.
Для объяснения поведения автор предоставил следующую картинку:
Я не могу понять, какой бин зависит и почему каждый доступ к прокси messageBuilder
порождает новую реализацию бина.Почему для первого случая ситуация иная?Не могли бы вы объяснить это?Насколько я понимаю - прокси все равно создаются - используя CGLIB или динамический прокси, так что в любом случае прокси вводится