There is only one "randomBean" because the default scope is "singleton".(To force Spring to produce a new bean instance each time one is needed, you should declare the bean's scope attribute to be prototype)
singleton
This scopes the bean definition to a single instance per Spring IoC
container (default).
prototype
This scopes a single bean definition to have any number of object
instances.
Spring guarantees that method randomBean()
will return the same reference as one which was injected into AnotherBean By using proxies.
In order to generate proxies, Spring uses a third party library called CGLIB.
Spring enhances classes by generating a CGLIB subclass which
interacts with the Spring container to respect bean scoping
semantics for methods.
Each such bean method will be overridden in the generated subclass,
only delegating to the actual bean method implementation if the
container actually requests the construction of a new instance.
Otherwise, a call to such an bean method serves as a reference back
to the container, obtaining the corresponding bean by name.
see org.springframework.context.annotation.ConfigurationClassEnhancer.BeanMethodInterceptor
// To handle the case of an inter-bean method reference, we must explicitly check the
// container for already cached instances.
// First, check to see if the requested bean is a FactoryBean. If so, create a subclass
// proxy that intercepts calls to getObject() and returns any cached bean instance.
// This ensures that the semantics of calling a FactoryBean from within @Bean methods
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
if (factoryContainsBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) && factoryContainsBean(beanName)) {
Object factoryBean = this.beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// Pass through - scoped proxy factory beans are a special case and should not
// be further proxied
}
else {
// It is a candidate FactoryBean - go ahead with enhancement
return enhanceFactoryBean(factoryBean.getClass(), beanName);
}
}
If you want to get two different beans, you should change the default scope by @Scope
@Configuration
public class Config {
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RandomBean randomBean(){
return new RandomBean();
}
@Bean
public AnotherBean anotherBean(){
return new AnotherBean(randomBean()); // this line
}
}