为什么将CGLIB原型注入Singleton,每次访问原型都会创建一个新对象?]

问题描述 投票:0回答:1

免责声明:

我已经阅读了有关JDK动态代理和CGLIB的专心研究人员:https://stackoverflow.com/a/21762454/2674303

我已阅读以下有趣的文章:Injecting Spring Prototype bean into Singleton bean

第一种情况:

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();
    }
    ....
}

Singleton:

@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。

为了解释行为作者提供了下图:

enter image description here

我无法理解哪个bean是依赖的,为什么每次访问代理messageBuilder都会使新bean实例化。为什么对于第一种情况,情况有所不同?你能解释一下吗?据我了解-代理无论如何都可以创建-使用CGLIB或使用动态代理,以便无论如何都可以注入代理]

免责声明:我已经阅读了有关JDK动态代理和CGLIB的专心研究人员:https://stackoverflow.com/a/21762454/2674303我已经阅读了以下有趣的文章:注入Spring原型bean ...

java spring scope singleton instantiation
1个回答
0
投票

如果您定义一个具有prototype范围的bean,当从Spring上下文中引用该bean时,ApplicationContext将返回一个新实例。在您的第一个示例中,当创建MessageBuilder singleton

bean时,将创建MessageService prototype
© www.soinside.com 2019 - 2024. All rights reserved.