问题
spring boot中我们常常会在configuration类中通过@Bean注解去声明Bean。
但是很多人不清楚默认情况下,通过@Bean注解声明的Bean的名称是什么?
请问,如下代码声明bean的名称是什么?
@Configuration
public class LogAutoConfigure {
@Bean
public Queue queueTest() {
return new Queue("log-queue", true);
}
}
为什么我们要关注声明bean的名称,这是由于spring容器中的bean默认是单例模式的,如果声明的bean的名称一样,就无法识别出具体调用哪一个。在调用的时候就会出错。
The bean 'queueTest', defined in class path resource [com/hcf/base/log/config/LogDataSourceConfig.class], could not be registered. A bean with that name has already been defined in class path resource
试验
@Configuration
public class LogConfigure {
@Bean(name="queue-test")
public Queue queue() {
return new Queue("log-queue1", true);
}
@Bean
public Queue queueTest() {
return new Queue("log-queue2", true);
}
}
使用单元测试去获取spring容器中的baen
@Component
public class ApplicationContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public ApplicationContextHelper() {
}
/**
* 实现ApplicationContextAware接口的回调方法,设置上下文环境
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHelper.applicationContext = applicationContext;
}
/**
* 获得spring上下文
* @return
*/
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public Object getBean(String beanName) {
return applicationContext != null ? applicationContext.getBean(beanName) : null;
}
}
@SpringBootTest(classes = LogApplication.class)
class LogApplicationTests {
@Autowired
ApplicationContextHelper contextHelper;
@Test
void testGetBean(){
Queue queue1 = (Queue) contextHelper.getBean("queue-test");
System.out.println(queue1);
Queue queue2 = (Queue) contextHelper.getBean("queueTest");
System.out.println(queue2);
}
}
执行单元测试的结果:
Queue [name=log-queue1, durable=true, autoDelete=false, exclusive=false, arguments={}, actualName=log-queue1]
Queue [name=log-queue2, durable=true, autoDelete=false, exclusive=false, arguments={}, actualName=log-queue2]
结论
通过观察我们不难发现,默认情况下,使用 @Bean声明一个bean,bean的名称由方法名决定。此外,可以通过@Bean注解里面的name属性主动设置bean的名称。
注入指定名称的bean
@Autowired
@Qualifier("queue-test")
private Queue queue;
典型场景
多数据源配置场景:
每个数据源都使用setDataSource()方法配置数据源,所以要使用@Bean(name = “j3sqlDataSource”)中通过name主动说明bean的名字
消息队列中,多队列声明
这里通过采用不同的方法名,声明多个队列和交换器,避免bean的名称重复
总结
1、spring boot中通过@Bean声明bean,默认情况下,bean的名称由方法名决定。另外,可以通过@Bean注解里面的name属性主动设置bean的名称。
2、通过@Autowired和@Qualifier(“queue-test”)结合使用,可以注入指定名称的bean
更多精彩,关注我吧。