是否可以使用原型范围创建基于导入java的配置的bean?
我的意思是,如果我有以下示例代码:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(
SpringTopLevelConfig.class);
for (int i = 0; i < 2; i++) {
System.out.println(applicationContext.getBean(Student.class));
}
哪里
public class Notebook {
static int idCounter = 1;
private final int id;
@Override
public String toString() {
return "Notebook{" +
"id=" + id +
'}';
}
public Notebook() {
id = idCounter++;
}
}
public class Student {
private final Notebook notebook;
@Override
public String toString() {
return "Student{" +
"notebook=" + notebook +
'}';
}
public Student(Notebook notebook) {
this.notebook = notebook;
}
}
Spring Config是:
@Configuration
public class SpringTopLevelConfig {
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Bean
Notebook notebook(){
return new Notebook();
}
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Bean
Student student(){
return new Student(notebook());
}
}
正如所料,每个学生都有自己的笔记本:
Student{notebook=Notebook{id=1}}
Student{notebook=Notebook{id=2}}
但是,如果我尝试将配置分成多个类,我发现所有示例都建议使用@Autowire
来完成此任务:
@Configuration
@Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig {
@Autowired
Notebook notebook;
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Bean
Student student(){
return new Student(notebook);
}
}
@Configuration
public class SpringConfigSecondLevel {
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Bean
Notebook notebook(){
return new Notebook();
}
}
然而,现在学生最终共享一个笔记本,这不是我想要实现的行为。
Student{notebook=Notebook{id=1}}
Student{notebook=Notebook{id=1}}
是否有一种弹簧方式可以使用拆分配置类实现SCOPE_PROTOTYPE行为,还是需要创建一个NotebookFactory
bean来防止学生在同一个笔记本上互相争斗?
答案 0 :(得分:1)
这两个配置文件方法没有预期的结果,因为您在SpringTopLevelConfig类中自动装配笔记本。该笔记本实例将被创建一次,并从所有其他学生对象中使用,因为当您创建学生时,在学生构造函数中传递该笔记本实例而不是notebook()bean方法。您可以通过自动装配整个配置类来传递学生构造函数中的notebook()bean方法,以便您可以调用它:
@Configuration
@Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig {
@Autowired SpringConfigSecondLevel springConfigSecondLevel;
@Scope("prototype")
@Bean
Student student(){
return new Student(springConfigSecondLevel.notebook());
}
}
@Configuration
public class SpringConfigSecondLevel {
@Scope("prototype")
@Bean
Notebook notebook(){
return new Notebook();
}
}
答案 1 :(得分:1)
由于Notebook实例是@Autowired,因此在创建springTopLevelConfig单例bean时将创建一次。从弹簧调试级别日志
可以看出这一点14:59:15.631 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'springTopLevelConfig'
14:59:15.631 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'springTopLevelConfig'
14:59:15.639 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Registered injected element on class [com.example.spring.prototype_level.SpringTopLevelConfig$$EnhancerBySpringCGLIB$$2fffb2e0]: AutowiredFieldElement for com.example.spring.prototype_level.Notebook com.example.spring.prototype_level.SpringTopLevelConfig.notebook
14:59:15.640 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'springTopLevelConfig' to allow for resolving potential circular references
14:59:15.673 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected method of bean 'springTopLevelConfig': AutowiredFieldElement for com.example.spring.prototype_level.Notebook com.example.spring.prototype_level.SpringTopLevelConfig.notebook
14:59:15.682 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'notebook'
14:59:15.682 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.682 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.684 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'com.example.spring.prototype_level.SpringConfigSecondLevel' to allow for resolving potential circular references
14:59:15.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.731 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'notebook'
14:59:15.732 [main] DEBUG o.s.b.f.a.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'springTopLevelConfig' to bean named 'notebook'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'springTopLevelConfig'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor'
14:59:15.733 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:59:15.736 [main] DEBUG o.s.c.a.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@391663bd]
14:59:15.736 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
14:59:15.739 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
14:59:15.739 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
14:59:15.740 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
14:59:15.740 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:59:15.740 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:59:15.752 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=1}}
14:59:15.753 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:59:15.753 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:59:15.753 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=1}}
另一种方法是使用applicationContext注入Notebook实例,如下所示
@Configuration
@Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig{
@Autowired
private ApplicationContext applicationContext;
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Bean
Student student(){
return new Student(applicationContext.getBean(Notebook.class));
}
}
现在,每次创建Student实例时,spring都会创建Notebook实例。春天记录也是这样说的
14:55:51.255 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'springTopLevelConfig'
14:55:51.255 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'springTopLevelConfig'
14:55:51.258 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'springTopLevelConfig' to allow for resolving potential circular references
14:55:51.284 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'springTopLevelConfig'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.285 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.287 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'com.example.spring.prototype_level.SpringConfigSecondLevel' to allow for resolving potential circular references
14:55:51.292 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.295 [main] DEBUG o.s.c.a.AnnotationConfigApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor@1396a464]
14:55:51.297 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
14:55:51.300 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
14:55:51.301 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
14:55:51.302 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
14:55:51.302 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:55:51.305 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:55:51.342 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'notebook'
14:55:51.342 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.352 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'notebook'
14:55:51.354 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=1}}
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'student'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTopLevelConfig'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'notebook'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'com.example.spring.prototype_level.SpringConfigSecondLevel'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'notebook'
14:55:51.355 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'student'
Student{notebook=Notebook{id=2}}
答案 2 :(得分:1)
其他人解释了为什么你的第一次尝试不起作用。我只建议一个不需要使用@Autowired
字段的解决方案。
@Configuration
@Import(SpringConfigSecondLevel.class)
public class SpringTopLevelConfig {
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Bean
public Student student(Notebook notebook) {
return new Student(notebook);
}
}
如果只是添加类型Notebook
的方法参数,Spring容器将自动为您提供新实例。