任何人都可以解释为什么静态方法上的@Bean
返回2个不同的实例?
我可以理解,类@Bean
之类的非静态方法的A
返回相同的实例,因为默认范围是单例。
如果我尝试在服务中使用B
注入类@Autowire
它将无法工作,所以看起来它不是由Spring App Context加载的。所以使用像D
这样的类会是类似的!
我想不是因为@PropertySource
我们需要另外使用(用于占位符):
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
如果我们从中删除@Bean,它将无效。
是否存在其他用例,在静态方法上使用@Bean会很有用?
实施例
我跑的时候:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Conf.class})
public class Test {
@org.junit.Test
public void test(){
}
}
的
@Configuration
@ComponentScan
public class Conf {
@Bean
public A aaa(){
return new A();
}
@Bean
public static B bbb(){
return new B();
}
@Bean
@Scope("prototype")
public C ccc(){
return new C();
}
public static D ddd(){
return new D();
}
@PostConstruct
public void post(){
System.out.println(aaa());
System.out.println(aaa());
System.out.println(bbb());
System.out.println(bbb());
System.out.println(ccc());
System.out.println(ccc());
System.out.println(ddd());
System.out.println(ddd());
}
}
public class A {
}
public class B {
}
public class C {
}
public class D {
}
我明白了:
uk.co.xxx.unit.A@6caf0677
uk.co.xxx.unit.A@6caf0677
uk.co.xxx.unit.B@413d1baf
uk.co.xxx.unit.B@16eb3ea3
uk.co.xxx.unit.C@353352b6
uk.co.xxx.unit.C@4681c175
uk.co.xxx.unit.D@57a78e3
uk.co.xxx.unit.D@402c4085
答案 0 :(得分:8)
因为您为bbb()
的每个方法调用创建了一个新对象。 bean之间的依赖关系(如果你只是调用bean生成方法)以这种方式工作,为你的配置类创建一个代理,并且代理拦截对bean方法的方法调用以提供正确的bean(单例,原型等)。 )。但是,静态方法不会被代理,因此当您调用静态方法时,Spring并不知道它,您只需获取常规Java对象。使用PropertySourcesPlaceholderConfigurer它是不同的,因为该方法不是在该类中直接调用的,bean只会在使用它的地方注入。
答案 1 :(得分:3)
@Bean注释方法获取代理以提供正确的bean实例。静态方法不会被代理。因此,在您的情况下,每次bbb()调用都会给出一个新的B实例。
PropertySourcesPlaceholderConfigurer类是一种特殊的bean,因为它实现了BeanFactoryPostProcessor。在容器生命周期中,BeanFactoryPostProcessor对象必须早于@Configuration-annotated类的对象进行实例化。此外,您不需要调用此静态方法。
请参阅java doc中的Bootstrapping部分:[http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/context/annotation/Bean.html][1]
必须特别考虑返回的@Bean方法 Spring BeanFactoryPostProcessor(BFPP)类型。因为BFPP对象 必须在容器生命周期的早期实例化,他们可以 干扰注释的处理,如@Autowired,@ Value, 和@Configuration类中的@PostConstruct。避免这些 生命周期问题,标记BFPP - 将@Bean方法返回为静态