I read these lines from a colleague's code:
@Bean(name = "mysql")
@ConfigurationProperties(prefix = "spring.mysql")
@Primary
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public ClassA classA () {
return new ClassA (this.mysqlDataSource());
}
@Bean
public ClassB classB () {
return new ClassB (this.mysqlDataSource());
}
I thought this will create 2 DataSources for Bean classA and classB. for injecting the datasource, we need something like:
@Bean
public ClassA classA (DataSource ds) {
return new ClassA (ds);
}
But Spring just create one datasource, and this.mysqlDataSource() returns the same one everytime. how does it happen? If I do need another DataSource, i need create it on the fly?
Spring says @Component
and @Configuration
has different meanings.
If you use @Configuration
instead of @Component
, CGLIB proxying will be used.
"The @Bean
methods in a regular Spring component are processed differently than their counterparts inside a Spring @Configuration
class. The difference is that @Component
classes are not enhanced with CGLIB
to intercept the invocation of methods and fields. CGLIB proxying is the means by which invoking methods or fields within @Bean
methods in @Configuration
classes creates bean metadata references to collaborating objects; such methods are not invoked with normal Java semantics but rather go through the container in order to provide the usual lifecycle management and proxying of Spring beans even when referring to other beans via programmatic calls to @Bean
methods. In contrast, invoking a method or field in an @Bean
method within a plain @Component
class has standard Java semantics, with no special CGLIB
processing or other constraints applying."
https://docs.spring.io/spring/docs/5.0.4.RELEASE/spring-framework-reference/core.html#spring-core
Alternatively, you can keep @ConfigurationProperties
in the class level and remove @Bean
from DataSource
so that mysqlDataSource()
will be treated as a regular method..