静态方法上的@Bean注释

Emi*_*and 7 spring

任何人都可以解释为什么@Bean静态方法返回2个不同的实例?

我可以理解,@Bean在类非A返回相同实例的非静态方法上,因为默认范围是单例.

如果我尝试注入类B@Autowire的服务将无法正常工作,所以它看起来像它不是由Spring应用程序上下文加载.所以使用D类似的类会是类似的!我想不是因为@PropertySource我们需要另外使用(用于占位符):

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}
Run Code Online (Sandbox Code Playgroud)

如果我们从中删除@Bean,它将无法工作.

还有其他用例,在静态方法上使用@Bean会有用吗?

例:

当我跑:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {Conf.class})
public class Test {
    @org.junit.Test
    public void test(){
    }
}
Run Code Online (Sandbox Code Playgroud)

对于

@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 {
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

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
Run Code Online (Sandbox Code Playgroud)

dun*_*nni 9

因为您为每个方法调用创建一个新对象bbb().bean之间的依赖关系(如果你只是调用bean生成方法)以这种方式工作,为你的配置类创建一个代理,并且代理拦截对bean方法的方法调用以提供正确的bean(单例,原型等). ).但是,静态方法不会被代理,因此当您调用静态方法时,Spring不知道它,您只需获取常规Java对象.使用PropertySourcesPlaceholderConfigurer它是不同的,因为该方法不是在该类中直接调用的,所以bean只会在使用它的地方注入.


Inv*_*r53 5

@Bean 注释的方法被代理以提供正确的 bean 实例。静态方法不会被代理。因此,在您的情况下,每次调用 bbb() 都会给出一个新的 B 实例。

PropertySourcesPlaceholderConfigurer 类是一种特殊的 bean,因为它实现了 BeanFactoryPostProcessor。在容器生命周期中,BeanFactoryPostProcessor 对象必须早于@Configuration-annotated 类的对象被实例化。你也不需要调用这个静态方法。

请参阅 java 文档中的 Bootstrapping 部分:[ http://docs.spring.io/spring/docs/4.2.x/javadoc-api/org/springframework/context/annotation/Bean.html][1]

必须特别考虑返回 Spring BeanFactoryPostProcessor (BFPP) 类型的 @Bean 方法。由于 BFPP 对象必须在容器生命周期的早期实例化,因此它们可能会干扰 @Configuration 类中的 @Autowired、@Value 和 @PostConstruct 等注释的处理。为避免这些生命周期问题,请将返回 BFPP 的 @Bean 方法标记为静态