回顾问题Autowire a bean within Spring's Java configuration我有一个问题。
@Configuration
public class Config {
@Bean
public RandomBean randomBean(){
return new RandomBean();
}
@Bean
public AnotherBean anotherBean(){
return new AnotherBean(randomBean()); // this line
}
}
Spring如何保证方法randomBean()
将返回与注入AnotherBean
的方法相同的引用?
是通过代理实现的吗?
另一方面,以提供依赖关系作为方法参数来做这件事显而易见:
@Configuration
public class Config {
@Bean
public RandomBean randomBean(){
return new RandomBean();
}
@Bean
public AnotherBean anotherBean(RandomBean randomBean){
return new AnotherBean(randomBean);
}
}
编辑最后,我发现了Further information about how Java-based configuration works internally主题中描述的这种行为。
答案 0 :(得分:7)
只有一个" randomBean"因为默认范围是" singleton" 。(为了在每次需要时强制Spring生成一个新的bean实例,你应该声明bean的scope属性是原型)
<强>单强>
这将bean定义范围限定为每个Spring IoC的单个实例 容器(默认)。
<强>原型强>
这使单个bean定义的范围包含任意数量的对象 实例
Spring保证方法randomBean()
将返回与注入AnotherBean的引用相同的引用使用代理。
为了生成代理,Spring使用名为 CGLIB 的第三方库。
Spring通过生成 CGLIB 子类来增强类 与Spring容器交互以尊重bean的范围 方法的语义。
每个这样的bean方法都将在生成的子类中重写, 如果是,只委托给实际的bean方法实现 容器实际上请求新实例的构造。
否则,对这种bean方法的调用将作为参考 到容器,按名称获取相应的bean。
请参阅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);
}
}
如果您想获得两个不同的bean,则应该通过@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
}
}
答案 1 :(得分:1)
根据Spring文档,只有在@Bean
内声明@Configuration
方法时才可能注入bean。它使用CGLIB,所有@Configuration
类都由它子类化。
请检查此参考https://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-java-bean-annotation,“7.12.4使用@Configuration注释”部分。您可以从原始来源找到您的问题的答案。