先说结论
@Bean 可以用在任意方法上。 -- 也可以用在注解上面。
@Bean 仅在Spring创建bean时起作用。
这应该算一个小技巧,在一个平常类(非@Configuration class)中@Bean method,需要的时候直接导入该类即可。
补充一句,@Import 在 4.2 版本之前只能导入配置类,4.2及以后可以导入任意类。
再来说说起因
在看Spring Boot源码的时候,发现很多平常类(非@Configuration class)中都有 @Bean method,甚是疑惑。
开始以为 Spring 会直接探测 @Bean method,然后创建相应的bean。于是手动测试了一番,代码如下(Spring Boot项目):
public class _TestBean { @Bean(name = "joke") public User user() { User user = new User(); user.setName("joke"); return user; } }
@Configuration public class _TestBeanConfig { @Autowired @Qualifier("joke") private User joke; @Autowired private User user; @PostConstruct public void print() { System.out.println(joke); System.out.println("---"); System.out.println(user); } }
结果,启动失败,报错内容是user依赖不满足!
所以之前的推测明显不成立, Spring不会扫描平常类中的@Bean method。
再次尝试
模仿Spring Boot源码中的使用方式:@Import,
@Configuration @Import(value = _TestBean.class) public class _TestBeanConfig { @Autowired @Qualifier("joke") private User joke; @Autowired private User user; @PostConstruct public void print() { System.out.println(joke); System.out.println("---"); System.out.println(user); } }
再次启动,成功,并顺利打印出所需信息。
就是说,使用@Import时,Spring会扫描被导入的类中的@Bean method,并执行(创建相应bean)。
查了下@Import,原文是这么说的:
Indicates one or more @Configuration classes to import.
又查了下@Configuration,说法如下:
Indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.
同时,@Configuration又被注解了@Component。
于是推测,Spring 在创建bean时,就会扫描其中的 @Bean method。
第三次测试如下:
@Component public class _TestBean { @Bean(name = "joke") public User user() { User user = new User(); user.setName("joke"); return user; } }
@Configuration // @Import(value = _TestBean.class) public class _TestBeanConfig { @Autowired @Qualifier("joke") private User joke; @Autowired private User user; @PostConstruct public void print() { System.out.println(joke); System.out.println("---"); System.out.println(user); } }
果然,顺利启动,并打印出所需信息。
于是得出最开始的结论:
@Bean 可以用在任意方法上。 -- 也可以用在注解上面。
@Bean 仅在Spring创建bean时起作用。