problem
In spring boot, we often declare Bean through @Bean annotation in configuration class.
But many people do not know what the name of the bean declared through the @Bean annotation is by default?
Excuse me, what is the name of the bean declared in the following code?
@Configuration
public class LogAutoConfigure {
@Bean
public Queue queueTest() {
return new Queue("log-queue", true);
}
}
Why do we need to pay attention to the name of the declared bean? This is because the bean in the spring container is in singleton mode by default. If the declared bean names are the same, it is impossible to identify which one to call. There will be an error when calling.
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
test
@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);
}
}
Use unit test to get baen in spring container
@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);
}
}
The result of executing the unit test:
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]
in conclusion
Through observation, it is not difficult to find that by default, @Bean is used to declare a bean, and the name of the bean is determined by the method name. In addition, you can actively set the name of the bean through the name attribute in the @Bean annotation.
Inject the bean with the specified name
@Autowired
@Qualifier("queue-test")
private Queue queue;
Typical scene
Multi-data source configuration scenario:
Each data source uses the setDataSource() method to configure the data source, so it is necessary to use @Bean(name = "j3sqlDataSource") to actively specify the name of the bean through the name. In the
message queue, the multi-queue declaration
is adopted here Different method names, declare multiple queues and exchanges to avoid duplication of bean names
to sum up
1. Spring boot declares beans through @Bean. By default, the name of the bean is determined by the method name. In addition, you can actively set the name of the bean through the name attribute in the @Bean annotation.
2. By combining @Autowired and @Qualifier("queue-test"), you can inject a bean with a specified name
More exciting, follow me.