Search code examples
spring-bootdependency-injectioncoding-style

Someone can explain to me for a use case of springboot injection


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?


Solution

  • 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..